You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
8.8 KiB
Python
190 lines
8.8 KiB
Python
8 months ago
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
import json
|
||
|
from dateutil.relativedelta import relativedelta
|
||
|
|
||
|
from odoo import models, api, fields, _, Command
|
||
|
from odoo.tools import format_date
|
||
|
from odoo.exceptions import UserError
|
||
|
|
||
|
|
||
|
class MulticurrencyRevaluationWizard(models.TransientModel):
|
||
|
_name = 'account.multicurrency.revaluation.wizard'
|
||
|
_description = 'Multicurrency Revaluation Wizard'
|
||
|
|
||
|
company_id = fields.Many2one('res.company', default=lambda self: self.env.company)
|
||
|
journal_id = fields.Many2one(
|
||
|
comodel_name='account.journal',
|
||
|
compute='_compute_accounting_values',
|
||
|
inverse='_inverse_revaluation_journal',
|
||
|
compute_sudo=True,
|
||
|
domain=[('type', '=', 'general')],
|
||
|
required=True,
|
||
|
readonly=False,
|
||
|
)
|
||
|
date = fields.Date(default=lambda self: self._context.get('date').get('date_to'), required=True) # TODO change defult dates
|
||
|
reversal_date = fields.Date(required=True)
|
||
|
expense_provision_account_id = fields.Many2one(
|
||
|
comodel_name='account.account',
|
||
|
compute='_compute_accounting_values',
|
||
|
inverse='_inverse_expense_provision_account',
|
||
|
compute_sudo=True,
|
||
|
string="Expense Account",
|
||
|
required=True,
|
||
|
readonly=False,
|
||
|
)
|
||
|
income_provision_account_id = fields.Many2one(
|
||
|
comodel_name='account.account',
|
||
|
compute='_compute_accounting_values',
|
||
|
inverse='_inverse_income_provision_account',
|
||
|
compute_sudo=True,
|
||
|
string="Income Account",
|
||
|
required=True,
|
||
|
readonly=False,
|
||
|
)
|
||
|
preview_data = fields.Text(compute='_compute_preview_data')
|
||
|
show_warning_move_id = fields.Many2one('account.move', compute='_compute_show_warning')
|
||
|
|
||
|
@api.model
|
||
|
def default_get(self, default_fields):
|
||
|
rec = super(MulticurrencyRevaluationWizard, self).default_get(default_fields)
|
||
|
if 'reversal_date' in default_fields:
|
||
|
rec['reversal_date'] = fields.Date.to_date(self._context.get('date').get('date_to')) + relativedelta(days=1)
|
||
|
if not self._context.get('revaluation_no_loop') and not self.with_context(revaluation_no_loop=True)._get_move_vals()['line_ids']:
|
||
|
raise UserError(_("No adjustment needed"))
|
||
|
return rec
|
||
|
|
||
|
@api.depends('expense_provision_account_id', 'income_provision_account_id', 'reversal_date')
|
||
|
def _compute_show_warning(self):
|
||
|
for record in self:
|
||
|
last_move = self.env['account.move.line'].search([
|
||
|
('account_id', 'in', (record.expense_provision_account_id + record.income_provision_account_id).ids),
|
||
|
('date', '<', record.reversal_date),
|
||
|
], order='date desc', limit=1).move_id
|
||
|
record.show_warning_move_id = False if last_move.reversed_entry_id else last_move
|
||
|
|
||
|
@api.depends('expense_provision_account_id', 'income_provision_account_id', 'date', 'journal_id')
|
||
|
def _compute_preview_data(self):
|
||
|
preview_columns = [
|
||
|
{'field': 'account_id', 'label': _("Account")},
|
||
|
{'field': 'name', 'label': _("Label")},
|
||
|
{'field': 'debit', 'label': _("Debit"), 'class': 'text-right text-nowrap'},
|
||
|
{'field': 'credit', 'label': _("Credit"), 'class': 'text-right text-nowrap'},
|
||
|
]
|
||
|
for record in self:
|
||
|
preview_vals = [self.env['account.move']._move_dict_to_preview_vals(
|
||
|
self._get_move_vals(),
|
||
|
record.company_id.currency_id)
|
||
|
]
|
||
|
record.preview_data = json.dumps({
|
||
|
'groups_vals': preview_vals,
|
||
|
'options': {
|
||
|
'columns': preview_columns,
|
||
|
},
|
||
|
})
|
||
|
|
||
|
@api.depends('company_id')
|
||
|
def _compute_accounting_values(self):
|
||
|
for record in self:
|
||
|
record.journal_id = record.company_id.account_revaluation_journal_id
|
||
|
record.expense_provision_account_id = record.company_id.account_revaluation_expense_provision_account_id
|
||
|
record.income_provision_account_id = record.company_id.account_revaluation_income_provision_account_id
|
||
|
|
||
|
def _inverse_revaluation_journal(self):
|
||
|
for record in self:
|
||
|
record.company_id.sudo().account_revaluation_journal_id = record.journal_id
|
||
|
|
||
|
def _inverse_expense_provision_account(self):
|
||
|
for record in self:
|
||
|
record.company_id.sudo().account_revaluation_expense_provision_account_id = record.expense_provision_account_id
|
||
|
|
||
|
def _inverse_income_provision_account(self):
|
||
|
for record in self:
|
||
|
record.company_id.sudo().account_revaluation_income_provision_account_id = record.income_provision_account_id
|
||
|
|
||
|
@api.model
|
||
|
def _get_move_vals(self):
|
||
|
def _get_model_id(parsed_line, selected_model):
|
||
|
for dummy, parsed_res_model, parsed_res_id in parsed_line:
|
||
|
if parsed_res_model == selected_model:
|
||
|
return parsed_res_id
|
||
|
|
||
|
def _get_adjustment_balance(line):
|
||
|
for column in line.get('columns'):
|
||
|
if column.get('expression_label') == 'adjustment':
|
||
|
return column.get('no_format')
|
||
|
|
||
|
report = self.env.ref('account_reports.multicurrency_revaluation_report')
|
||
|
included_line_id = report.line_ids.filtered(lambda l: l.code == 'multicurrency_included').id
|
||
|
generic_included_line_id = report._get_generic_line_id('account.report.line', included_line_id)
|
||
|
options = self._context
|
||
|
report_lines = report._get_lines(options)
|
||
|
move_lines = []
|
||
|
|
||
|
for report_line in report._get_unfolded_lines(report_lines, generic_included_line_id):
|
||
|
parsed_line_id = report._parse_line_id(report_line.get('id'))
|
||
|
# parsed_line_id[-1][-2] corresponds to res_model of the current line
|
||
|
if parsed_line_id[-1][-2] == 'account.move.line':
|
||
|
account_id = _get_model_id(parsed_line_id, 'account.account')
|
||
|
currency_id = _get_model_id(parsed_line_id, 'res.currency')
|
||
|
balance = _get_adjustment_balance(report_line)
|
||
|
move_lines.append(Command.create({
|
||
|
'name': _(
|
||
|
"Provision for %(for_cur)s (1 %(comp_cur)s = %(rate)s %(for_cur)s)",
|
||
|
for_cur=self.env['res.currency'].browse(currency_id).display_name,
|
||
|
comp_cur=self.env.company.currency_id.display_name,
|
||
|
rate=self._context['currency_rates'][str(currency_id)]['rate']
|
||
|
),
|
||
|
'debit': balance if balance > 0 else 0,
|
||
|
'credit': -balance if balance < 0 else 0,
|
||
|
'amount_currency': 0,
|
||
|
'currency_id': currency_id,
|
||
|
'account_id': account_id,
|
||
|
}))
|
||
|
if balance < 0:
|
||
|
move_line_name = _("Expense Provision for %s", self.env['res.currency'].browse(currency_id).display_name)
|
||
|
else:
|
||
|
move_line_name = _("Income Provision for %s", self.env['res.currency'].browse(currency_id).display_name)
|
||
|
move_lines.append(Command.create({
|
||
|
'name': move_line_name,
|
||
|
'debit': -balance if balance < 0 else 0,
|
||
|
'credit': balance if balance > 0 else 0,
|
||
|
'amount_currency': 0,
|
||
|
'currency_id': currency_id,
|
||
|
'account_id': self.expense_provision_account_id.id if balance < 0 else self.income_provision_account_id.id,
|
||
|
}))
|
||
|
|
||
|
return {
|
||
|
'ref': _("Foreign currencies adjustment entry as of %s", format_date(self.env, self.date)),
|
||
|
'journal_id': self.journal_id.id,
|
||
|
'date': self.date,
|
||
|
'line_ids': move_lines,
|
||
|
}
|
||
|
|
||
|
def create_entries(self):
|
||
|
self.ensure_one()
|
||
|
move_vals = self._get_move_vals()
|
||
|
if move_vals['line_ids']:
|
||
|
move = self.env['account.move'].create(move_vals)
|
||
|
move.action_post()
|
||
|
reverse_move = move._reverse_moves(default_values_list=[{
|
||
|
'ref': _("Reversal of: %s", move.ref),
|
||
|
}])
|
||
|
reverse_move.date = self.reversal_date
|
||
|
reverse_move.action_post()
|
||
|
|
||
|
form = self.env.ref('account.view_move_form', False)
|
||
|
ctx = self.env.context.copy()
|
||
|
ctx.pop('id', '')
|
||
|
return {
|
||
|
'type': 'ir.actions.act_window',
|
||
|
'res_model': "account.move",
|
||
|
'res_id': move.id,
|
||
|
'view_mode': "form",
|
||
|
'view_id': form.id,
|
||
|
'views': [(form.id, 'form')],
|
||
|
'context': ctx,
|
||
|
}
|
||
|
raise UserError(_("No provision needed was found."))
|