2020-09-07 14:31:18 +02:00
|
|
|
# Copyright 2016-2020 Onestein (<https://www.onestein.eu>)
|
2018-10-22 12:27:50 +02:00
|
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
|
|
|
|
|
|
|
from odoo import _, api, fields, models
|
|
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
|
|
|
|
|
|
class AccountInvoiceSpreadLine(models.Model):
|
2020-09-07 14:17:04 +02:00
|
|
|
_name = "account.spread.line"
|
|
|
|
_description = "Account Spread Lines"
|
|
|
|
_order = "date"
|
2018-10-22 12:27:50 +02:00
|
|
|
|
2020-09-07 14:17:04 +02:00
|
|
|
name = fields.Char("Description", readonly=True)
|
2020-09-07 14:31:18 +02:00
|
|
|
amount = fields.Float(digits="Account", required=True)
|
2018-10-22 12:27:50 +02:00
|
|
|
date = fields.Date(required=True)
|
2020-09-07 14:31:18 +02:00
|
|
|
spread_id = fields.Many2one("account.spread", ondelete="cascade")
|
2020-09-07 14:17:04 +02:00
|
|
|
move_id = fields.Many2one("account.move", string="Journal Entry", readonly=True)
|
2018-10-22 12:27:50 +02:00
|
|
|
|
|
|
|
def create_and_reconcile_moves(self):
|
|
|
|
grouped_lines = {}
|
|
|
|
for spread_line in self:
|
|
|
|
spread = spread_line.spread_id
|
|
|
|
spread_line_list = grouped_lines.get(
|
2020-09-07 14:17:04 +02:00
|
|
|
spread, self.env["account.spread.line"]
|
|
|
|
)
|
|
|
|
grouped_lines.update({spread: spread_line_list + spread_line})
|
2018-10-22 12:27:50 +02:00
|
|
|
for spread in grouped_lines:
|
|
|
|
created_moves = grouped_lines[spread]._create_moves()
|
|
|
|
|
|
|
|
if created_moves:
|
|
|
|
post_msg = _("Created move(s) ")
|
2018-12-20 16:39:00 +01:00
|
|
|
post_msg += ", ".join(
|
2020-09-07 14:17:04 +02:00
|
|
|
"<a href=# data-oe-model=account.move data-oe-id=%d"
|
|
|
|
">%s</a>" % (move.id, move.name)
|
|
|
|
for move in created_moves
|
|
|
|
)
|
2018-10-22 12:27:50 +02:00
|
|
|
spread.message_post(body=post_msg)
|
2020-09-07 14:31:18 +02:00
|
|
|
if spread.invoice_id.state == "posted":
|
|
|
|
spread._reconcile_spread_moves(created_moves)
|
|
|
|
spread._post_spread_moves(created_moves)
|
2018-10-22 12:27:50 +02:00
|
|
|
|
|
|
|
def create_move(self):
|
2020-09-07 14:31:18 +02:00
|
|
|
"""Button to manually create a move from a spread line entry."""
|
2018-10-22 12:27:50 +02:00
|
|
|
self.ensure_one()
|
|
|
|
self.create_and_reconcile_moves()
|
|
|
|
|
|
|
|
def _create_moves(self):
|
2019-06-04 13:38:00 +02:00
|
|
|
if self.filtered(lambda l: l.move_id):
|
2020-09-07 14:17:04 +02:00
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"This spread line is already linked to a "
|
|
|
|
"journal entry! Please post or delete it."
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
created_moves = self.env["account.move"]
|
2018-10-22 12:27:50 +02:00
|
|
|
for line in self:
|
|
|
|
move_vals = line._prepare_move()
|
2020-09-07 14:17:04 +02:00
|
|
|
move = self.env["account.move"].create(move_vals)
|
2020-09-07 14:31:18 +02:00
|
|
|
line.move_id = move
|
2018-10-22 12:27:50 +02:00
|
|
|
created_moves += move
|
|
|
|
return created_moves
|
|
|
|
|
|
|
|
def _prepare_move(self):
|
|
|
|
self.ensure_one()
|
|
|
|
|
2020-09-07 14:17:04 +02:00
|
|
|
spread_date = self.env.context.get("spread_date") or self.date
|
2018-10-22 12:27:50 +02:00
|
|
|
spread = self.spread_id
|
|
|
|
analytic = spread.account_analytic_id
|
2020-09-07 14:31:18 +02:00
|
|
|
analytic_tags = []
|
|
|
|
if self.env["account.analytic.tag"].check_access_rights(
|
|
|
|
"read", raise_exception=False
|
|
|
|
):
|
|
|
|
analytic_tags = [(6, 0, spread.analytic_tag_ids.ids)]
|
2018-10-22 12:27:50 +02:00
|
|
|
|
|
|
|
company_currency = spread.company_id.currency_id
|
|
|
|
current_currency = spread.currency_id
|
|
|
|
not_same_curr = company_currency != current_currency
|
2018-12-20 10:21:14 +01:00
|
|
|
amount = current_currency._convert(
|
2020-09-07 14:17:04 +02:00
|
|
|
self.amount, company_currency, spread.company_id, spread_date
|
|
|
|
)
|
|
|
|
|
2020-09-07 14:31:18 +02:00
|
|
|
debit_credit = spread.invoice_type in ["in_invoice", "out_refund"]
|
|
|
|
|
2020-09-07 14:17:04 +02:00
|
|
|
line_ids = [
|
|
|
|
(
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
{
|
2020-09-07 14:31:18 +02:00
|
|
|
"name": spread.name,
|
|
|
|
"account_id": spread.debit_account_id.id
|
|
|
|
if debit_credit
|
|
|
|
else spread.credit_account_id.id,
|
2020-09-07 14:17:04 +02:00
|
|
|
"debit": amount if amount > 0.0 else 0.0,
|
|
|
|
"credit": -amount if amount < 0.0 else 0.0,
|
|
|
|
"partner_id": self.spread_id.invoice_id.partner_id.id,
|
|
|
|
"analytic_account_id": analytic.id,
|
|
|
|
"analytic_tag_ids": analytic_tags,
|
|
|
|
"currency_id": not_same_curr and current_currency.id or False,
|
|
|
|
"amount_currency": not_same_curr and -1.0 * self.amount or 0.0,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
{
|
2020-09-07 14:31:18 +02:00
|
|
|
"name": spread.name,
|
|
|
|
"account_id": spread.credit_account_id.id
|
|
|
|
if debit_credit
|
|
|
|
else spread.debit_account_id.id,
|
2020-09-07 14:17:04 +02:00
|
|
|
"credit": amount if amount > 0.0 else 0.0,
|
|
|
|
"debit": -amount if amount < 0.0 else 0.0,
|
|
|
|
"partner_id": self.spread_id.invoice_id.partner_id.id,
|
|
|
|
"analytic_account_id": analytic.id,
|
|
|
|
"analytic_tag_ids": analytic_tags,
|
|
|
|
"currency_id": not_same_curr and current_currency.id or False,
|
|
|
|
"amount_currency": not_same_curr and self.amount or 0.0,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
]
|
2018-10-22 12:27:50 +02:00
|
|
|
|
|
|
|
return {
|
2020-09-07 14:17:04 +02:00
|
|
|
"name": self.name or "/",
|
|
|
|
"ref": self.name,
|
|
|
|
"date": spread_date,
|
|
|
|
"journal_id": spread.journal_id.id,
|
|
|
|
"line_ids": line_ids,
|
|
|
|
"company_id": spread.company_id.id,
|
2020-09-07 14:31:18 +02:00
|
|
|
"partner_id": spread.invoice_id.partner_id.id,
|
2018-10-22 12:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def open_move(self):
|
2020-09-07 14:31:18 +02:00
|
|
|
"""Used by a button to manually view a move from a spread line entry."""
|
2018-10-22 12:27:50 +02:00
|
|
|
self.ensure_one()
|
|
|
|
return {
|
2020-09-07 14:17:04 +02:00
|
|
|
"name": _("Journal Entry"),
|
|
|
|
"view_mode": "form",
|
|
|
|
"res_model": "account.move",
|
|
|
|
"view_id": False,
|
|
|
|
"type": "ir.actions.act_window",
|
|
|
|
"res_id": self.move_id.id,
|
2018-10-22 12:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def unlink_move(self):
|
2020-09-07 14:31:18 +02:00
|
|
|
"""Used by a button to manually unlink a move from a spread line entry."""
|
2018-10-22 12:27:50 +02:00
|
|
|
for line in self:
|
|
|
|
move = line.move_id
|
2020-09-07 14:17:04 +02:00
|
|
|
if move.state == "posted":
|
2018-10-22 12:27:50 +02:00
|
|
|
move.button_cancel()
|
|
|
|
move.line_ids.remove_move_reconcile()
|
|
|
|
post_msg = _("Deleted move %s") % line.move_id.id
|
2020-09-07 14:31:18 +02:00
|
|
|
move.with_context(force_delete=True).unlink()
|
2018-10-22 12:27:50 +02:00
|
|
|
line.move_id = False
|
|
|
|
line.spread_id.message_post(body=post_msg)
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
def _create_entries(self):
|
|
|
|
"""Find spread line entries where date is in the past and
|
|
|
|
create moves for them. Method also called by the cron job.
|
|
|
|
"""
|
2020-09-07 14:17:04 +02:00
|
|
|
lines = self.search(
|
|
|
|
[("date", "<=", fields.Date.today()), ("move_id", "=", False)]
|
|
|
|
)
|
2018-10-22 12:27:50 +02:00
|
|
|
lines.create_and_reconcile_moves()
|
2019-04-05 14:40:52 +02:00
|
|
|
|
2020-09-07 14:17:04 +02:00
|
|
|
unposted_moves = (
|
|
|
|
self.search([("move_id", "!=", False)])
|
|
|
|
.mapped("move_id")
|
|
|
|
.filtered(lambda m: m.state != "posted")
|
|
|
|
)
|
|
|
|
unposted_moves.filtered(lambda m: m.company_id.force_move_auto_post).post()
|
|
|
|
|
|
|
|
spreads_to_archive = (
|
|
|
|
self.env["account.spread"]
|
|
|
|
.search([("all_posted", "=", True)])
|
2020-09-07 14:31:18 +02:00
|
|
|
.filtered(lambda s: s.company_id.auto_archive_spread)
|
2020-09-07 14:17:04 +02:00
|
|
|
)
|
|
|
|
spreads_to_archive.write({"active": False})
|