Sharing my experience with controlling asset management under Multi company and multi currency environment.
Assumption->
*Multi Company Setup, Company A with base currency INR.
*Company B with base currency AED
* Secondary currency = USD with following rates
USD to INR= 70
USD to AED = 4
Steps to reproduce issue->
1) Your Adminstrator User's company preference is Company A(INR)
2) Asset created under Company B for 12 USD.
3) Next Depreciation date 24june 2019 of 1 USD
4) Cron Job/Schduler ran on 24june from Adminstrator User's account automatically.
5) Expected result:
Journal entry currency amount= 1usd
Base amount conversion to AED = 4AED
6) Actual result:
Journal entry currency amount= 1usd
Base amount conversion computed with USD to INR i.e 70.
This happened because cron job ran through Adminstrator User
Adminstrator User's preference/login company was Company A and base currency was INR
7) I feel this is bug in Odoo system and below is patch for same->
# Patch code highlighted in bold color
# please note i have created a seperate cron job user called "admincopy". Cron job will run from "admincopy" user
class AssetManagementMulticompany(models.Model):
_inherit = "account.asset.asset"
@api.model
def _cron_generate_entries(self):
"""Overidden method.
*Context cron=True added.
* If cron =True logic added for multi currency in create move method of dep.lines."""
self.with_context(cron=True).compute_generated_entries(datetime.today())
class AccountAssetDepreciationLineMulticompany(models.Model):
_inherit = 'account.asset.depreciation.line'
@api.multi
def create_move(self, post_move=True):
"""
* Overridden method to compute amount currency if asset/prepaid expense is in multi currency for multicompany.
* See context cron=True, run multicompany ,multicurrency logic for move entry.
"""
created_moves = self.env['account.move']
technical_user = self.env['res.users'].search([('login', '=', 'admincopy')])
cronjob_user = self.env.uid
prec = self.env['decimal.precision'].precision_get('Account')
for line in self:
if line.move_id:
raise UserError(_('This depreciation is already linked to a journal entry! Please post or delete it.'))
category_id = line.asset_id.category_id
depreciation_date = self.env.context.get('depreciation_date') or line.depreciation_date or fields.Date.context_today(self)
company_currency = line.asset_id.company_id.currency_id
current_currency = line.asset_id.currency_id
# If asset/Deferred Revenues ran through cron job
if self.env.context.get('cron'):
try:
technical_user[0].sudo().write({'company_id': line.asset_id.company_id.id})
current_currency.env.uid = technical_user[0].id
amount = current_currency.with_context(date=depreciation_date).compute(line.amount, company_currency)
self.env.uid = cronjob_user
except Exception as IndexErrorException:
_logger.error("Error occurred during asset/prepaid expense cron for Line Id=%s. Error is %s"
% (line, IndexErrorException))
amount = current_currency.with_context(date=depreciation_date).compute(line.amount, company_currency)
else:
amount = current_currency.with_context(date=depreciation_date).compute(line.amount, company_currency)
asset_name = line.asset_id.name + ' (%s/%s)' % (line.sequence, len(line.asset_id.depreciation_line_ids))
move_line_1 = {
'name': asset_name,
'account_id': category_id.account_depreciation_id.id,
'debit': 0.0 if float_compare(amount, 0.0, precision_digits=prec) > 0 else -amount,
'credit': amount if float_compare(amount, 0.0, precision_digits=prec) > 0 else 0.0,
'journal_id': category_id.journal_id.id,
'partner_id': line.asset_id.partner_id.id,
'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'sale' else False,
'currency_id': company_currency != current_currency and current_currency.id or False,
'amount_currency': company_currency != current_currency and - 1.0 * line.amount or 0.0,
}
move_line_2 = {
'name': asset_name,
'account_id': category_id.account_depreciation_expense_id.id,
'credit': 0.0 if float_compare(amount, 0.0, precision_digits=prec) > 0 else -amount,
'debit': amount if float_compare(amount, 0.0, precision_digits=prec) > 0 else 0.0,
'journal_id': category_id.journal_id.id,
'partner_id': line.asset_id.partner_id.id,
'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'purchase' else False,
'currency_id': company_currency != current_currency and current_currency.id or False,
'amount_currency': company_currency != current_currency and line.amount or 0.0,
}
move_vals = {
'ref': line.asset_id.code,
'date': depreciation_date or False,
'journal_id': category_id.journal_id.id,
'line_ids': [(0, 0, move_line_1), (0, 0, move_line_2)],
}
move = self.env['account.move'].create(move_vals)
line.write({'move_id': move.id, 'move_check': True})
created_moves |= move
if post_move and created_moves:
created_moves.filtered(lambda m: any(m.asset_depreciation_ids.mapped('asset_id.category_id.open_asset'))).post()
return [x.id for x in created_moves]