From c0511fded9e05bc9d45f6988d8923baa933def62 Mon Sep 17 00:00:00 2001
From: Ajmalcybrosys
Date: Mon, 28 Oct 2019 20:18:44 +0530
Subject: [PATCH] [FIX] Bug Fixed 'base_accounting_kit'
---
base_accounting_kit/README.rst | 2 +-
base_accounting_kit/__manifest__.py | 8 +-
.../data/account_asset_data.xml | 2 -
base_accounting_kit/doc/RELEASE_NOTES.md | 11 +
base_accounting_kit/models/account_asset.py | 783 +++++++++++-------
base_accounting_kit/models/account_move.py | 59 +-
.../models/product_template.py | 12 +-
.../report/account_asset_report.py | 51 +-
.../report/account_asset_report_views.xml | 15 +-
.../report/cash_flow_report.xml | 65 +-
.../security/account_asset_security.xml | 7 -
.../static/description/index.html | 183 ++--
.../static/src/js/account_asset.js | 4 +-
.../static/src/less/account_asset.less | 9 +
.../static/src/scss/account_asset.scss | 9 -
.../views/account_asset_templates.xml | 2 +-
.../views/account_asset_views.xml | 173 ++--
...voice_views.xml => account_move_views.xml} | 7 +-
base_accounting_kit/views/product_views.xml | 17 +
.../asset_depreciation_confirmation_wizard.py | 19 +-
...depreciation_confirmation_wizard_views.xml | 13 +-
base_accounting_kit/wizard/asset_modify.py | 48 +-
.../wizard/asset_modify_views.xml | 2 +-
.../wizard/cash_flow_report.xml | 12 +-
.../wizard/recurring_payments_wizard.xml | 16 +-
25 files changed, 784 insertions(+), 745 deletions(-)
create mode 100644 base_accounting_kit/doc/RELEASE_NOTES.md
create mode 100644 base_accounting_kit/static/src/less/account_asset.less
delete mode 100644 base_accounting_kit/static/src/scss/account_asset.scss
rename base_accounting_kit/views/{account_invoice_views.xml => account_move_views.xml} (64%)
create mode 100644 base_accounting_kit/views/product_views.xml
diff --git a/base_accounting_kit/README.rst b/base_accounting_kit/README.rst
index e85d30080..e50aeb947 100644
--- a/base_accounting_kit/README.rst
+++ b/base_accounting_kit/README.rst
@@ -1,5 +1,5 @@
Accounting Kit
-=============================
+==============
* Full accounting kit for Odoo 13 community editions
Installation
diff --git a/base_accounting_kit/__manifest__.py b/base_accounting_kit/__manifest__.py
index 69ed2210d..82bf1ee34 100644
--- a/base_accounting_kit/__manifest__.py
+++ b/base_accounting_kit/__manifest__.py
@@ -21,8 +21,8 @@
#############################################################################
{
- 'name': 'Odoo 13 Full Accounting Kit',
- 'version': '13.0.1.0.0',
+ 'name': 'Odoo 13 Accounting',
+ 'version': '13.0.1.1.1',
'category': 'Accounting',
'summary': """ This Module will bring back the accounting features such Asset Management, Accounting Reports, PDC Management,
Account Lock dates, Customer Credit Limit and Follow Ups, Day book,
@@ -31,7 +31,7 @@
Odoo 13 Accounting,Accounting Reports,Odoo13 Accounting PDF Reports, Asset Management,
Customer Credit Limit, Recurring Payment,
PDC Management, Customer Follow-up,
- Lock Dates into Odoo 13 Community Edition, Odoo Accounting,Odoo 13 Accounting Reports,Odoo 13, Full Accounting, Complete Accounting, Odoo Community Accounting, Accounting for odoo 13, Full Accounting Package, Financial Reports, Financial Report for Odoo 13""",
+ Lock Dates into Odoo 13 Community Edition, Odoo Accounting,Odoo 13 Accounting Reports,Odoo 13""",
'author': ' Odoo SA,Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'company': 'Cybrosys Techno Solutions',
@@ -57,7 +57,7 @@
'wizard/asset_depreciation_confirmation_wizard_views.xml',
'wizard/asset_modify_views.xml',
'views/account_asset_views.xml',
- 'views/account_invoice_views.xml',
+ 'views/account_move_views.xml',
'views/account_asset_templates.xml',
'views/product_template_views.xml',
'wizard/financial_report.xml',
diff --git a/base_accounting_kit/data/account_asset_data.xml b/base_accounting_kit/data/account_asset_data.xml
index 28f3491ba..3f9a28987 100644
--- a/base_accounting_kit/data/account_asset_data.xml
+++ b/base_accounting_kit/data/account_asset_data.xml
@@ -1,6 +1,5 @@
-
Account Asset: Generate asset entries
@@ -11,5 +10,4 @@
-1
-
\ No newline at end of file
diff --git a/base_accounting_kit/doc/RELEASE_NOTES.md b/base_accounting_kit/doc/RELEASE_NOTES.md
new file mode 100644
index 000000000..ec6b1e22c
--- /dev/null
+++ b/base_accounting_kit/doc/RELEASE_NOTES.md
@@ -0,0 +1,11 @@
+## Module
+
+#### 23.10.2019
+#### Version 13.0.1.0.0
+#### ADD
+- Initial commit for Dynamic Cash Book Report
+
+#### 28.10.2019
+#### Version 13.0.1.1.1
+#### FIX
+- Function Asset Changed.
diff --git a/base_accounting_kit/models/account_asset.py b/base_accounting_kit/models/account_asset.py
index d4d3fdd69..a95d47f6d 100644
--- a/base_accounting_kit/models/account_asset.py
+++ b/base_accounting_kit/models/account_asset.py
@@ -22,10 +22,12 @@
import calendar
from datetime import date, datetime
+
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
+from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import float_compare, float_is_zero
@@ -35,36 +37,57 @@ class AccountAssetCategory(models.Model):
active = fields.Boolean(default=True)
name = fields.Char(required=True, index=True, string="Asset Type")
- account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
- analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tag')
- account_asset_id = fields.Many2one('account.account', string='Asset Account', required=True, domain=[('internal_type','=','other'), ('deprecated', '=', False)], help="Account used to record the purchase of the asset at its original price.")
- account_depreciation_id = fields.Many2one('account.account', string='Depreciation Entries: Asset Account', required=True, domain=[('internal_type','=','other'), ('deprecated', '=', False)], help="Account used in the depreciation entries, to decrease the asset value.")
- account_depreciation_expense_id = fields.Many2one('account.account', string='Depreciation Entries: Expense Account', required=True, domain=[('internal_type','=','other'), ('deprecated', '=', False)], oldname='account_income_recognition_id', help="Account used in the periodical entries, to record a part of the asset as expense.")
- journal_id = fields.Many2one('account.journal', string='Journal', required=True)
- company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env['res.company']._company_default_get('account.asset.category'))
- method = fields.Selection([('linear', 'Linear'), ('degressive', 'Degressive')], string='Computation Method', required=True, default='linear',
+ account_analytic_id = fields.Many2one('account.analytic.account',
+ string='Analytic Account')
+ account_asset_id = fields.Many2one('account.account',
+ string='Asset Account', required=True,
+ domain=[('internal_type', '=', 'other'),
+ ('deprecated', '=', False)],
+ help="Account used to record the purchase of the asset at its original price.")
+ account_depreciation_id = fields.Many2one('account.account',
+ string='Depreciation Entries: Asset Account',
+ required=True, domain=[
+ ('internal_type', '=', 'other'), ('deprecated', '=', False)],
+ help="Account used in the depreciation entries, to decrease the asset value.")
+ account_depreciation_expense_id = fields.Many2one('account.account',
+ string='Depreciation Entries: Expense Account',
+ required=True, domain=[
+ ('internal_type', '=', 'other'), ('deprecated', '=', False)],
+ oldname='account_income_recognition_id',
+ help="Account used in the periodical entries, to record a part of the asset as expense.")
+ journal_id = fields.Many2one('account.journal', string='Journal',
+ required=True)
+ company_id = fields.Many2one('res.company', string='Company',
+ required=True, default=lambda self: self.env[
+ 'res.company']._company_default_get('account.asset.category'))
+ method = fields.Selection(
+ [('linear', 'Linear'), ('degressive', 'Degressive')],
+ string='Computation Method', required=True, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n"
- " * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
- " * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
- method_number = fields.Integer(string='Number of Depreciations', default=5, help="The number of depreciations needed to depreciate your asset")
- method_period = fields.Integer(string='Period Length', default=1, help="State here the time between 2 depreciations, in months", required=True)
+ " * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
+ " * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
+ method_number = fields.Integer(string='Number of Depreciations', default=5,
+ help="The number of depreciations needed to depreciate your asset")
+ method_period = fields.Integer(string='Period Length', default=1,
+ help="State here the time between 2 depreciations, in months",
+ required=True)
method_progress_factor = fields.Float('Degressive Factor', default=0.3)
- method_time = fields.Selection([('number', 'Number of Entries'), ('end', 'Ending Date')], string='Time Method', required=True, default='number',
+ method_time = fields.Selection(
+ [('number', 'Number of Entries'), ('end', 'Ending Date')],
+ string='Time Method', required=True, default='number',
help="Choose the method to use to compute the dates and number of entries.\n"
- " * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n"
- " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.")
+ " * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n"
+ " * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.")
method_end = fields.Date('Ending date')
- prorata = fields.Boolean(string='Prorata Temporis', help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first of January')
- open_asset = fields.Boolean(string='Auto-Confirm Assets', help="Check this if you want to automatically confirm the assets of this category when created by invoices.")
- group_entries = fields.Boolean(string='Group Journal Entries', help="Check this if you want to group the generated entries by categories.")
- type = fields.Selection([('sale', 'Sale: Revenue Recognition'), ('purchase', 'Purchase: Asset')], required=True, index=True, default='purchase')
- date_first_depreciation = fields.Selection([
- ('last_day_period', 'Based on Last Day of Purchase Period'),
- ('manual', 'Manual (Defaulted on Purchase Date)')],
- string='Depreciation Dates', default='manual', required=True,
- help='The way to compute the date of the first depreciation.\n'
- ' * Based on last day of purchase period: The depreciation dates will be based on the last day of the purchase month or the purchase year (depending on the periodicity of the depreciations).\n'
- ' * Based on purchase date: The depreciation dates will be based on the purchase date.')
+ prorata = fields.Boolean(string='Prorata Temporis',
+ help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first of January')
+ open_asset = fields.Boolean(string='Auto-confirm Assets',
+ help="Check this if you want to automatically confirm the assets of this category when created by invoices.")
+ group_entries = fields.Boolean(string='Group Journal Entries',
+ help="Check this if you want to group the generated entries by categories.")
+ type = fields.Selection([('sale', 'Sale: Revenue Recognition'),
+ ('purchase', 'Purchase: Asset')], required=True,
+ index=True, default='purchase')
@api.onchange('account_asset_id')
def onchange_account_asset(self):
@@ -92,68 +115,119 @@ class AccountAssetAsset(models.Model):
_description = 'Asset/Revenue Recognition'
_inherit = ['mail.thread']
- entry_count = fields.Integer(compute='_entry_count', string='# Asset Entries')
- name = fields.Char(string='Asset Name', required=True, readonly=True, states={'draft': [('readonly', False)]})
- code = fields.Char(string='Reference', size=32, readonly=True, states={'draft': [('readonly', False)]})
- value = fields.Float(string='Gross Value', required=True, readonly=True, digits=0, states={'draft': [('readonly', False)]}, oldname='purchase_value')
- currency_id = fields.Many2one('res.currency', string='Currency', required=True, readonly=True, states={'draft': [('readonly', False)]},
- default=lambda self: self.env.user.company_id.currency_id.id)
- company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, states={'draft': [('readonly', False)]},
- default=lambda self: self.env['res.company']._company_default_get('account.asset.asset'))
+ entry_count = fields.Integer(compute='_entry_count',
+ string='# Asset Entries')
+ name = fields.Char(string='Asset Name', required=True, readonly=True,
+ states={'draft': [('readonly', False)]})
+ code = fields.Char(string='Reference', size=32, readonly=True,
+ states={'draft': [('readonly', False)]})
+ value = fields.Float(string='Gross Value', required=True, readonly=True,
+ digits=0, states={'draft': [('readonly', False)]},
+ oldname='purchase_value')
+ currency_id = fields.Many2one('res.currency', string='Currency',
+ required=True, readonly=True,
+ states={'draft': [('readonly', False)]},
+ default=lambda
+ self: self.env.user.company_id.currency_id.id)
+ company_id = fields.Many2one('res.company', string='Company',
+ required=True, readonly=True,
+ states={'draft': [('readonly', False)]},
+ default=lambda self: self.env[
+ 'res.company']._company_default_get(
+ 'account.asset.asset'))
note = fields.Text()
- category_id = fields.Many2one('account.asset.category', string='Category', required=True, change_default=True, readonly=True, states={'draft': [('readonly', False)]})
- date = fields.Date(string='Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, default=fields.Date.context_today, oldname="purchase_date")
- state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')], 'Status', required=True, copy=False, default='draft',
+ category_id = fields.Many2one('account.asset.category', string='Category',
+ required=True, change_default=True,
+ readonly=True,
+ states={'draft': [('readonly', False)]})
+ date = fields.Date(string='Date', required=True, readonly=True,
+ states={'draft': [('readonly', False)]},
+ default=fields.Date.context_today,
+ oldname="purchase_date")
+ state = fields.Selection(
+ [('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')],
+ 'Status', required=True, copy=False, default='draft',
help="When an asset is created, the status is 'Draft'.\n"
- "If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n"
- "You can manually close an asset when the depreciation is over. If the last line of depreciation is posted, the asset automatically goes in that status.")
+ "If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n"
+ "You can manually close an asset when the depreciation is over. If the last line of depreciation is posted, the asset automatically goes in that status.")
active = fields.Boolean(default=True)
- partner_id = fields.Many2one('res.partner', string='Partner', readonly=True, states={'draft': [('readonly', False)]})
- method = fields.Selection([('linear', 'Linear'), ('degressive', 'Degressive')], string='Computation Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, default='linear',
+ partner_id = fields.Many2one('res.partner', string='Partner',
+ readonly=True,
+ states={'draft': [('readonly', False)]})
+ method = fields.Selection(
+ [('linear', 'Linear'), ('degressive', 'Degressive')],
+ string='Computation Method', required=True, readonly=True,
+ states={'draft': [('readonly', False)]}, default='linear',
help="Choose the method to use to compute the amount of depreciation lines.\n * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n"
- " * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
- method_number = fields.Integer(string='Number of Depreciations', readonly=True, states={'draft': [('readonly', False)]}, default=5, help="The number of depreciations needed to depreciate your asset")
- method_period = fields.Integer(string='Number of Months in a Period', required=True, readonly=True, default=12, states={'draft': [('readonly', False)]},
- help="The amount of time between two depreciations, in months")
- method_end = fields.Date(string='Ending Date', readonly=True, states={'draft': [('readonly', False)]})
- method_progress_factor = fields.Float(string='Degressive Factor', readonly=True, default=0.3, states={'draft': [('readonly', False)]})
- value_residual = fields.Float(compute='_amount_residual', method=True, digits=0, string='Residual Value')
- method_time = fields.Selection([('number', 'Number of Entries'), ('end', 'Ending Date')], string='Time Method', required=True, readonly=True, default='number', states={'draft': [('readonly', False)]},
+ " * Degressive: Calculated on basis of: Residual Value * Degressive Factor")
+ method_number = fields.Integer(string='Number of Depreciations',
+ readonly=True,
+ states={'draft': [('readonly', False)]},
+ default=5,
+ help="The number of depreciations needed to depreciate your asset")
+ method_period = fields.Integer(string='Number of Months in a Period',
+ required=True, readonly=True, default=12,
+ states={'draft': [('readonly', False)]},
+ help="The amount of time between two depreciations, in months")
+ method_end = fields.Date(string='Ending Date', readonly=True,
+ states={'draft': [('readonly', False)]})
+ method_progress_factor = fields.Float(string='Degressive Factor',
+ readonly=True, default=0.3, states={
+ 'draft': [('readonly', False)]})
+ value_residual = fields.Float(compute='_amount_residual', method=True,
+ digits=0, string='Residual Value')
+ method_time = fields.Selection(
+ [('number', 'Number of Entries'), ('end', 'Ending Date')],
+ string='Time Method', required=True, readonly=True, default='number',
+ states={'draft': [('readonly', False)]},
help="Choose the method to use to compute the dates and number of entries.\n"
" * Number of Entries: Fix the number of entries and the time between 2 depreciations.\n"
" * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond.")
- prorata = fields.Boolean(string='Prorata Temporis', readonly=True, states={'draft': [('readonly', False)]},
- help='Indicates that the first depreciation entry for this asset have to be done from the asset date (purchase date) instead of the first January / Start date of fiscal year')
- depreciation_line_ids = fields.One2many('account.asset.depreciation.line', 'asset_id', string='Depreciation Lines', readonly=True, states={'draft': [('readonly', False)], 'open': [('readonly', False)]})
- salvage_value = fields.Float(string='Salvage Value', digits=0, readonly=True, states={'draft': [('readonly', False)]},
- help="It is the amount you plan to have that you cannot depreciate.")
- invoice_id = fields.Many2one('account.move', string='Invoice', states={'draft': [('readonly', False)]}, copy=False)
- type = fields.Selection(related="category_id.type", string='Type', required=True)
- account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
- analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tag')
- date_first_depreciation = fields.Selection([
- ('last_day_period', 'Based on Last Day of Purchase Period'),
- ('manual', 'Manual')],
- string='Depreciation Dates', default='manual',
- readonly=True, states={'draft': [('readonly', False)]}, required=True,
- help='The way to compute the date of the first depreciation.\n'
- ' * Based on last day of purchase period: The depreciation dates will be based on the last day of the purchase month or the purchase year (depending on the periodicity of the depreciations).\n'
- ' * Based on purchase date: The depreciation dates will be based on the purchase date.\n')
- first_depreciation_manual_date = fields.Date(
- string='First Depreciation Date',
- readonly=True, states={'draft': [('readonly', False)]},
- help='Note that this date does not alter the computation of the first journal entry in case of prorata temporis assets. It simply changes its accounting date'
- )
+ prorata = fields.Boolean(string='Prorata Temporis', readonly=True,
+ states={'draft': [('readonly', False)]},
+ help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first January / Start date of fiscal year')
+ depreciation_line_ids = fields.One2many('account.asset.depreciation.line',
+ 'asset_id',
+ string='Depreciation Lines',
+ readonly=True, states={
+ 'draft': [('readonly', False)], 'open': [('readonly', False)]})
+ salvage_value = fields.Float(string='Salvage Value', digits=0,
+ readonly=True,
+ states={'draft': [('readonly', False)]},
+ help="It is the amount you plan to have that you cannot depreciate.")
+ invoice_id = fields.Many2one('account.move', string='Invoice',
+ states={'draft': [('readonly', False)]},
+ copy=False)
+ type = fields.Selection(related="category_id.type", string='Type',
+ required=True)
def unlink(self):
for asset in self:
if asset.state in ['open', 'close']:
- raise UserError(_('You cannot delete a document that is in %s state.') % (asset.state,))
+ raise UserError(
+ _('You cannot delete a document is in %s state.') % (
+ asset.state,))
for depreciation_line in asset.depreciation_line_ids:
if depreciation_line.move_id:
- raise UserError(_('You cannot delete a document that contains posted entries.'))
+ raise UserError(_(
+ 'You cannot delete a document that contains posted entries.'))
return super(AccountAssetAsset, self).unlink()
+ def _get_last_depreciation_date(self):
+ """
+ @param id: ids of a account.asset.asset objects
+ @return: Returns a dictionary of the effective dates of the last depreciation entry made for given asset ids. If there isn't any, return the purchase date of this asset
+ """
+ self.env.cr.execute("""
+ SELECT a.id as id, COALESCE(MAX(m.date),a.date) AS date
+ FROM account_asset_asset a
+ LEFT JOIN account_asset_depreciation_line rel ON (rel.asset_id = a.id)
+ LEFT JOIN account_move m ON (rel.move_id = m.id)
+ WHERE a.id IN %s
+ GROUP BY a.id, m.date """, (tuple(self.ids),))
+ result = dict(self.env.cr.fetchall())
+ return result
+
@api.model
def _cron_generate_entries(self):
self.compute_generated_entries(datetime.today())
@@ -166,128 +240,184 @@ class AccountAssetAsset(models.Model):
if asset_type:
type_domain = [('type', '=', asset_type)]
- ungrouped_assets = self.env['account.asset.asset'].search(type_domain + [('state', '=', 'open'), ('category_id.group_entries', '=', False)])
- created_move_ids += ungrouped_assets._compute_entries(date, group_entries=False)
-
- for grouped_category in self.env['account.asset.category'].search(type_domain + [('group_entries', '=', True)]):
- assets = self.env['account.asset.asset'].search([('state', '=', 'open'), ('category_id', '=', grouped_category.id)])
- created_move_ids += assets._compute_entries(date, group_entries=True)
+ ungrouped_assets = self.env['account.asset.asset'].search(
+ type_domain + [('state', '=', 'open'),
+ ('category_id.group_entries', '=', False)])
+ created_move_ids += ungrouped_assets._compute_entries(date,
+ group_entries=False)
+
+ for grouped_category in self.env['account.asset.category'].search(
+ type_domain + [('group_entries', '=', True)]):
+ assets = self.env['account.asset.asset'].search(
+ [('state', '=', 'open'),
+ ('category_id', '=', grouped_category.id)])
+ created_move_ids += assets._compute_entries(date,
+ group_entries=True)
return created_move_ids
- def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date):
- for record in self:
- amount = 0
- if sequence == undone_dotation_number:
- amount = residual_amount
- else:
- if record.method == 'linear':
- amount = amount_to_depr / (undone_dotation_number - len(posted_depreciation_line_ids))
- if record.prorata:
- amount = amount_to_depr / record.method_number
- if sequence == 1:
- date = record.date
- if record.method_period % 12 != 0:
- month_days = calendar.monthrange(date.year, date.month)[1]
- days = month_days - date.day + 1
- amount = (amount_to_depr / record.method_number) / month_days * days
- else:
- days = (record.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1
- amount = (amount_to_depr / record.method_number) / total_days * days
- elif record.method == 'degressive':
- amount = residual_amount * record.method_progress_factor
- if record.prorata:
- if sequence == 1:
- date = record.date
- if record.method_period % 12 != 0:
- month_days = calendar.monthrange(date.year, date.month)[1]
- days = month_days - date.day + 1
- amount = (residual_amount * record.method_progress_factor) / month_days * days
- else:
- days = (record.company_id.compute_fiscalyear_dates(date)['date_to'] - date).days + 1
- amount = (residual_amount * record.method_progress_factor) / total_days * days
- return amount
+ def _compute_board_amount(self, sequence, residual_amount, amount_to_depr,
+ undone_dotation_number,
+ posted_depreciation_line_ids, total_days,
+ depreciation_date):
+ amount = 0
+ if sequence == undone_dotation_number:
+ amount = residual_amount
+ else:
+ if self.method == 'linear':
+ amount = amount_to_depr / (undone_dotation_number - len(
+ posted_depreciation_line_ids))
+ if self.prorata:
+ amount = amount_to_depr / self.method_number
+ if sequence == 1:
+ if self.method_period % 12 != 0:
+ date = datetime.strptime(self.date, '%Y-%m-%d')
+ month_days = \
+ calendar.monthrange(date.year, date.month)[1]
+ days = month_days - date.day + 1
+ amount = (
+ amount_to_depr / self.method_number) / month_days * days
+ else:
+ days = (self.company_id.compute_fiscalyear_dates(
+ depreciation_date)[
+ 'date_to'] - depreciation_date).days + 1
+ amount = (
+ amount_to_depr / self.method_number) / total_days * days
+ elif self.method == 'degressive':
+ amount = residual_amount * self.method_progress_factor
+ if self.prorata:
+ if sequence == 1:
+ if self.method_period % 12 != 0:
+ date = datetime.strptime(self.date, '%Y-%m-%d')
+ month_days = \
+ calendar.monthrange(date.year, date.month)[1]
+ days = month_days - date.day + 1
+ amount = (
+ residual_amount * self.method_progress_factor) / month_days * days
+ else:
+ days = (self.company_id.compute_fiscalyear_dates(
+ depreciation_date)[
+ 'date_to'] - depreciation_date).days + 1
+ amount = (
+ residual_amount * self.method_progress_factor) / total_days * days
+ return amount
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
- for record in self:
- undone_dotation_number = record.method_number
- if record.method_time == 'end':
- end_date = record.method_end
- undone_dotation_number = 0
- while depreciation_date <= end_date:
- depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+record.method_period)
- undone_dotation_number += 1
- if record.prorata:
+ undone_dotation_number = self.method_number
+ if self.method_time == 'end':
+ end_date = datetime.strptime(str(self.method_end), DF).date()
+ undone_dotation_number = 0
+ while depreciation_date <= end_date:
+ depreciation_date = date(depreciation_date.year,
+ depreciation_date.month,
+ depreciation_date.day) + relativedelta(
+ months=+self.method_period)
undone_dotation_number += 1
- return undone_dotation_number
+ if self.prorata:
+ undone_dotation_number += 1
+ return undone_dotation_number
def compute_depreciation_board(self):
self.ensure_one()
- for record in self:
- posted_depreciation_line_ids = record.depreciation_line_ids.filtered(lambda x: x.move_check).sorted(key=lambda l: l.depreciation_date)
- unposted_depreciation_line_ids = record.depreciation_line_ids.filtered(lambda x: not x.move_check)
- # Remove old unposted depreciation lines. We cannot use unlink() with One2many field
- commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]
+ posted_depreciation_line_ids = self.depreciation_line_ids.filtered(
+ lambda x: x.move_check).sorted(key=lambda l: l.depreciation_date)
+ unposted_depreciation_line_ids = self.depreciation_line_ids.filtered(
+ lambda x: not x.move_check)
+
+ # Remove old unposted depreciation lines. We cannot use unlink() with One2many field
+ commands = [(2, line_id.id, False) for line_id in
+ unposted_depreciation_line_ids]
+
+ if self.value_residual != 0.0:
+ amount_to_depr = residual_amount = self.value_residual
+ if self.prorata:
+ # if we already have some previous validated entries, starting date is last entry + method perio
+ if posted_depreciation_line_ids and \
+ posted_depreciation_line_ids[-1].depreciation_date:
+ last_depreciation_date = datetime.strptime(
+ posted_depreciation_line_ids[-1].depreciation_date,
+ DF).date()
+ depreciation_date = last_depreciation_date + relativedelta(
+ months=+self.method_period)
+ else:
+ depreciation_date = datetime.strptime(
+ str(self._get_last_depreciation_date()[self.id]),
+ DF).date()
+ else:
+ # depreciation_date = 1st of January of purchase year if annual valuation, 1st of
+ # purchase month in other cases
+ if self.method_period >= 12:
+ if self.company_id.fiscalyear_last_month:
+ print(self.company_id.fiscalyear_last_month)
+ print(self.company_id.fiscalyear_last_day)
+ print(self.date)
+ asset_date = date(year=int(self.date.year),
+ month=int(
+ self.company_id.fiscalyear_last_month),
+ day=int(
+ self.company_id.fiscalyear_last_day)) + relativedelta(
+ days=1) + \
+ relativedelta(year=int(
+ self.date.year)) # e.g. 2018-12-31 +1 -> 2019
+ else:
+ asset_date = datetime.strptime(
+ self.date[:4] + '-01-01', DF).date()
+ else:
+ asset_date = datetime.strptime(self.date[:7] + '-01',
+ DF).date()
+ # if we already have some previous validated entries, starting date isn't 1st January but last entry + method period
+ if posted_depreciation_line_ids and \
+ posted_depreciation_line_ids[-1].depreciation_date:
+ last_depreciation_date = datetime.strptime(
+ posted_depreciation_line_ids[-1].depreciation_date,
+ DF).date()
+ depreciation_date = last_depreciation_date + relativedelta(
+ months=+self.method_period)
+ else:
+ depreciation_date = asset_date
+ day = depreciation_date.day
+ month = depreciation_date.month
+ year = depreciation_date.year
+ total_days = (year % 4) and 365 or 366
+
+ undone_dotation_number = self._compute_board_undone_dotation_nb(
+ depreciation_date, total_days)
+
+ for x in range(len(posted_depreciation_line_ids),
+ undone_dotation_number):
+ sequence = x + 1
+ amount = self._compute_board_amount(sequence, residual_amount,
+ amount_to_depr,
+ undone_dotation_number,
+ posted_depreciation_line_ids,
+ total_days,
+ depreciation_date)
+ amount = self.currency_id.round(amount)
+ if float_is_zero(amount,
+ precision_rounding=self.currency_id.rounding):
+ continue
+ residual_amount -= amount
+ vals = {
+ 'amount': amount,
+ 'asset_id': self.id,
+ 'sequence': sequence,
+ 'name': (self.code or '') + '/' + str(sequence),
+ 'remaining_value': residual_amount,
+ 'depreciated_value': self.value - (
+ self.salvage_value + residual_amount),
+ 'depreciation_date': depreciation_date.strftime(DF),
+ }
+ commands.append((0, False, vals))
+ # Considering Depr. Period as months
+ depreciation_date = date(year, month, day) + relativedelta(
+ months=+self.method_period)
+ day = depreciation_date.day
+ month = depreciation_date.month
+ year = depreciation_date.year
- if record.value_residual != 0.0:
- amount_to_depr = residual_amount = record.value_residual
+ self.write({'depreciation_line_ids': commands})
- # if we already have some previous validated entries, starting date is last entry + method period
- if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date:
- last_depreciation_date = fields.Date.from_string(posted_depreciation_line_ids[-1].depreciation_date)
- depreciation_date = last_depreciation_date + relativedelta(months=+record.method_period)
- else:
- # depreciation_date computed from the purchase date
- depreciation_date = record.date
- if record.date_first_depreciation == 'last_day_period':
- # depreciation_date = the last day of the month
- depreciation_date = depreciation_date + relativedelta(day=31)
- # ... or fiscalyear depending the number of period
- if record.method_period == 12:
- depreciation_date = depreciation_date + relativedelta(month=record.company_id.fiscalyear_last_month)
- depreciation_date = depreciation_date + relativedelta(day=record.company_id.fiscalyear_last_day)
- if depreciation_date < record.date:
- depreciation_date = depreciation_date + relativedelta(years=1)
- elif record.first_depreciation_manual_date and record.first_depreciation_manual_date != record.date:
- # depreciation_date set manually from the 'first_depreciation_manual_date' field
- depreciation_date = record.first_depreciation_manual_date
-
- total_days = (depreciation_date.year % 4) and 365 or 366
- month_day = depreciation_date.day
- undone_dotation_number = record._compute_board_undone_dotation_nb(depreciation_date, total_days)
-
- for x in range(len(posted_depreciation_line_ids), undone_dotation_number):
- sequence = x + 1
- amount = record._compute_board_amount(sequence, residual_amount, amount_to_depr, undone_dotation_number, posted_depreciation_line_ids, total_days, depreciation_date)
- amount = record.currency_id.round(amount)
- if float_is_zero(amount, precision_rounding=record.currency_id.rounding):
- continue
- residual_amount -= amount
- vals = {
- 'amount': amount,
- 'asset_id': record.id,
- 'sequence': sequence,
- 'name': (record.code or '') + '/' + str(sequence),
- 'remaining_value': residual_amount,
- 'depreciated_value': record.value - (record.salvage_value + residual_amount),
- 'depreciation_date': depreciation_date,
- }
- commands.append((0, False, vals))
-
- depreciation_date = depreciation_date + relativedelta(months=+record.method_period)
-
- if month_day > 28 and record.date_first_depreciation == 'manual':
- max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1]
- depreciation_date = depreciation_date.replace(day=min(max_day_in_month, month_day))
-
- # datetime doesn't take into account that the number of days is not the same for each month
- if not record.prorata and record.method_period % 12 != 0 and record.date_first_depreciation == 'last_day_period':
- max_day_in_month = calendar.monthrange(depreciation_date.year, depreciation_date.month)[1]
- depreciation_date = depreciation_date.replace(day=max_day_in_month)
-
- record.write({'depreciation_line_ids': commands})
-
- return True
+ return True
def validate(self):
self.write({'state': 'open'})
@@ -305,34 +435,22 @@ class AccountAssetAsset(models.Model):
for asset in self:
tracked_fields = ref_tracked_fields.copy()
if asset.method == 'linear':
- del(tracked_fields['method_progress_factor'])
+ del (tracked_fields['method_progress_factor'])
if asset.method_time != 'end':
- del(tracked_fields['method_end'])
+ del (tracked_fields['method_end'])
else:
- del(tracked_fields['method_number'])
- dummy, tracking_value_ids = asset._message_track(tracked_fields, dict.fromkeys(fields))
- asset.message_post(subject=_('Asset created'), tracking_value_ids=tracking_value_ids)
-
- def _return_disposal_view(self, move_ids):
- name = _('Disposal Move')
- view_mode = 'form'
- if len(move_ids) > 1:
- name = _('Disposal Moves')
- view_mode = 'tree,form'
- return {
- 'name': name,
- 'view_type': 'form',
- 'view_mode': view_mode,
- 'res_model': 'account.move',
- 'type': 'ir.actions.act_window',
- 'target': 'current',
- 'res_id': move_ids[0],
- }
+ del (tracked_fields['method_number'])
+ dummy, tracking_value_ids = asset._message_track(tracked_fields,
+ dict.fromkeys(
+ fields))
+ asset.message_post(subject=_('Asset created'),
+ tracking_value_ids=tracking_value_ids)
def _get_disposal_moves(self):
move_ids = []
for asset in self:
- unposted_depreciation_line_ids = asset.depreciation_line_ids.filtered(lambda x: not x.move_check)
+ unposted_depreciation_line_ids = asset.depreciation_line_ids.filtered(
+ lambda x: not x.move_check)
if unposted_depreciation_line_ids:
old_values = {
'method_end': asset.method_end,
@@ -340,41 +458,65 @@ class AccountAssetAsset(models.Model):
}
# Remove all unposted depr. lines
- commands = [(2, line_id.id, False) for line_id in unposted_depreciation_line_ids]
+ commands = [(2, line_id.id, False) for line_id in
+ unposted_depreciation_line_ids]
# Create a new depr. line with the residual amount and post it
- sequence = len(asset.depreciation_line_ids) - len(unposted_depreciation_line_ids) + 1
- today = fields.Datetime.today()
+ sequence = len(asset.depreciation_line_ids) - len(
+ unposted_depreciation_line_ids) + 1
+ today = datetime.today().strftime(DF)
vals = {
'amount': asset.value_residual,
'asset_id': asset.id,
'sequence': sequence,
'name': (asset.code or '') + '/' + str(sequence),
'remaining_value': 0,
- 'depreciated_value': asset.value - asset.salvage_value, # the asset is completely depreciated
+ 'depreciated_value': asset.value - asset.salvage_value,
+ # the asset is completely depreciated
'depreciation_date': today,
}
commands.append((0, False, vals))
- asset.write({'depreciation_line_ids': commands, 'method_end': today, 'method_number': sequence})
- tracked_fields = self.env['account.asset.asset'].fields_get(['method_number', 'method_end'])
- changes, tracking_value_ids = asset._message_track(tracked_fields, old_values)
+ asset.write(
+ {'depreciation_line_ids': commands, 'method_end': today,
+ 'method_number': sequence})
+ tracked_fields = self.env['account.asset.asset'].fields_get(
+ ['method_number', 'method_end'])
+ changes, tracking_value_ids = asset._message_track(
+ tracked_fields, old_values)
if changes:
- asset.message_post(subject=_('Asset sold or disposed. Accounting entry awaiting for validation.'), tracking_value_ids=tracking_value_ids)
- move_ids += asset.depreciation_line_ids[-1].create_move(post_move=False)
+ asset.message_post(subject=_(
+ 'Asset sold or disposed. Accounting entry awaiting for validation.'),
+ tracking_value_ids=tracking_value_ids)
+ move_ids += asset.depreciation_line_ids[-1].create_move(
+ post_move=False)
return move_ids
def set_to_close(self):
move_ids = self._get_disposal_moves()
if move_ids:
- return self._return_disposal_view(move_ids)
+ name = _('Disposal Move')
+ view_mode = 'form'
+ if len(move_ids) > 1:
+ name = _('Disposal Moves')
+ view_mode = 'tree,form'
+ return {
+ 'name': name,
+ 'view_type': 'form',
+ 'view_mode': view_mode,
+ 'res_model': 'account.move',
+ 'type': 'ir.actions.act_window',
+ 'target': 'current',
+ 'res_id': move_ids[0],
+ }
# Fallback, as if we just clicked on the smartbutton
return self.open_entries()
def set_to_draft(self):
self.write({'state': 'draft'})
- @api.depends('value', 'salvage_value', 'depreciation_line_ids.move_check', 'depreciation_line_ids.amount')
+ @api.depends('value', 'salvage_value', 'depreciation_line_ids.move_check',
+ 'depreciation_line_ids.amount')
def _amount_residual(self):
for record in self:
total_amount = 0.0
@@ -387,21 +529,18 @@ class AccountAssetAsset(models.Model):
def onchange_company_id(self):
self.currency_id = self.company_id.currency_id.id
- @api.onchange('date_first_depreciation')
- def onchange_date_first_depreciation(self):
- if self.date_first_depreciation == 'manual':
- self.first_depreciation_manual_date = self.date
-
@api.depends('depreciation_line_ids.move_id')
def _entry_count(self):
for asset in self:
- res = self.env['account.asset.depreciation.line'].search_count([('asset_id', '=', asset.id), ('move_id', '!=', False)])
+ res = self.env['account.asset.depreciation.line'].search_count(
+ [('asset_id', '=', asset.id), ('move_id', '!=', False)])
asset.entry_count = res or 0
@api.constrains('prorata', 'method_time')
def _check_prorata(self):
if self.prorata and self.method_time != 'number':
- raise ValidationError(_('Prorata temporis can be applied only for the "number of depreciations" time method.'))
+ raise ValidationError(_(
+ 'Prorata temporis can be applied only for time method "number of depreciations".'))
@api.onchange('category_id')
def onchange_category_id(self):
@@ -423,9 +562,6 @@ class AccountAssetAsset(models.Model):
'method_progress_factor': category.method_progress_factor,
'method_end': category.method_end,
'prorata': category.prorata,
- 'date_first_depreciation': category.date_first_depreciation,
- 'account_analytic_id': category.account_analytic_id.id,
- 'analytic_tag_ids': [(6, 0, category.analytic_tag_ids.ids)],
}
}
@@ -450,17 +586,17 @@ class AccountAssetAsset(models.Model):
@api.model
def create(self, vals):
- asset = super(AccountAssetAsset, self.with_context(mail_create_nolog=True)).create(vals)
+ asset = super(AccountAssetAsset,
+ self.with_context(mail_create_nolog=True)).create(vals)
asset.sudo().compute_depreciation_board()
return asset
def write(self, vals):
- for record in self:
- res = super(AccountAssetAsset, record).write(vals)
- if 'depreciation_line_ids' not in vals and 'state' not in vals:
- for rec in record:
- rec.compute_depreciation_board()
- return res
+ res = super(AccountAssetAsset, self).write(vals)
+ if 'depreciation_line_ids' not in vals and 'state' not in vals:
+ for rec in self:
+ rec.compute_depreciation_board()
+ return res
def open_entries(self):
move_ids = []
@@ -485,15 +621,23 @@ class AccountAssetDepreciationLine(models.Model):
name = fields.Char(string='Depreciation Name', required=True, index=True)
sequence = fields.Integer(required=True)
- asset_id = fields.Many2one('account.asset.asset', string='Asset', required=True, ondelete='cascade')
- parent_state = fields.Selection(related='asset_id.state', string='State of Asset')
- amount = fields.Float(string='Current Depreciation', digits=0, required=True)
- remaining_value = fields.Float(string='Next Period Depreciation', digits=0, required=True)
- depreciated_value = fields.Float(string='Cumulative Depreciation', required=True)
+ asset_id = fields.Many2one('account.asset.asset', string='Asset',
+ required=True, ondelete='cascade')
+ parent_state = fields.Selection(related='asset_id.state',
+ string='State of Asset')
+ amount = fields.Float(string='Current Depreciation', digits=0,
+ required=True)
+ remaining_value = fields.Float(string='Next Period Depreciation', digits=0,
+ required=True)
+ depreciated_value = fields.Float(string='Cumulative Depreciation',
+ required=True)
depreciation_date = fields.Date('Depreciation Date', index=True)
move_id = fields.Many2one('account.move', string='Depreciation Entry')
- move_check = fields.Boolean(compute='_get_move_check', string='Linked', track_visibility='always', store=True)
- move_posted_check = fields.Boolean(compute='_get_move_posted_check', string='Posted', track_visibility='always', store=True)
+ move_check = fields.Boolean(compute='_get_move_check', string='Linked',
+ track_visibility='always', store=True)
+ move_posted_check = fields.Boolean(compute='_get_move_posted_check',
+ string='Posted',
+ track_visibility='always', store=True)
@api.depends('move_id')
def _get_move_check(self):
@@ -507,72 +651,80 @@ class AccountAssetDepreciationLine(models.Model):
def create_move(self, post_move=True):
created_moves = self.env['account.move']
+ prec = self.env['decimal.precision'].precision_get('Account')
+ if self.mapped('move_id'):
+ raise UserError(_(
+ 'This depreciation is already linked to a journal entry! Please post or delete it.'))
for line in self:
- if line.move_id:
- raise UserError(_('This depreciation is already linked to a journal entry. Please post or delete it.'))
- move_vals = self._prepare_move(line)
+ 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
+ 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))
+ partner = self.env['res.partner']._find_accounting_partner(
+ line.asset_id.partner_id)
+ 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': partner.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': partner.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()
+ 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]
- def _prepare_move(self, line):
- category_id = line.asset_id.category_id
- account_analytic_id = line.asset_id.account_analytic_id
- analytic_tag_ids = line.asset_id.analytic_tag_ids
- 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
- prec = company_currency.decimal_places
- amount = current_currency._convert(
- line.amount, company_currency, line.asset_id.company_id, depreciation_date)
- 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,
- 'partner_id': line.asset_id.partner_id.id,
- 'analytic_account_id': account_analytic_id.id if category_id.type == 'sale' else False,
- 'analytic_tag_ids': [(6, 0, analytic_tag_ids.ids)] 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,
- 'partner_id': line.asset_id.partner_id.id,
- 'analytic_account_id': account_analytic_id.id if category_id.type == 'purchase' else False,
- 'analytic_tag_ids': [(6, 0, analytic_tag_ids.ids)] 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)],
- }
- return move_vals
-
- def _prepare_move_grouped(self):
- asset_id = self[0].asset_id
- category_id = asset_id.category_id # we can suppose that all lines have the same category
- account_analytic_id = asset_id.account_analytic_id
- analytic_tag_ids = asset_id.analytic_tag_ids
- depreciation_date = self.env.context.get('depreciation_date') or fields.Date.context_today(self)
+ def create_grouped_move(self, post_move=True):
+ if not self.exists():
+ return []
+
+ created_moves = self.env['account.move']
+ category_id = self[
+ 0].asset_id.category_id # we can suppose that all lines have the same category
+ depreciation_date = self.env.context.get(
+ 'depreciation_date') or fields.Date.context_today(self)
amount = 0.0
for line in self:
# Sum amount of all depreciation lines
company_currency = line.asset_id.company_id.currency_id
current_currency = line.asset_id.currency_id
- company = line.asset_id.company_id
- amount += current_currency._convert(line.amount, company_currency, company, fields.Date.today())
+ amount += current_currency.compute(line.amount, company_currency)
name = category_id.name + _(' (grouped)')
move_line_1 = {
@@ -581,8 +733,7 @@ class AccountAssetDepreciationLine(models.Model):
'debit': 0.0,
'credit': amount,
'journal_id': category_id.journal_id.id,
- 'analytic_account_id': account_analytic_id.id if category_id.type == 'sale' else False,
- 'analytic_tag_ids': [(6, 0, analytic_tag_ids.ids)] if category_id.type == 'sale' else False,
+ 'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'sale' else False,
}
move_line_2 = {
'name': name,
@@ -590,8 +741,7 @@ class AccountAssetDepreciationLine(models.Model):
'credit': 0.0,
'debit': amount,
'journal_id': category_id.journal_id.id,
- 'analytic_account_id': account_analytic_id.id if category_id.type == 'purchase' else False,
- 'analytic_tag_ids': [(6, 0, analytic_tag_ids.ids)] if category_id.type == 'purchase' else False,
+ 'analytic_account_id': category_id.account_analytic_id.id if category_id.type == 'purchase' else False,
}
move_vals = {
'ref': category_id.name,
@@ -599,15 +749,7 @@ class AccountAssetDepreciationLine(models.Model):
'journal_id': category_id.journal_id.id,
'line_ids': [(0, 0, move_line_1), (0, 0, move_line_2)],
}
-
- return move_vals
-
- def create_grouped_move(self, post_move=True):
- if not self.exists():
- return []
-
- created_moves = self.env['account.move']
- move = self.env['account.move'].create(self._prepare_move_grouped())
+ move = self.env['account.move'].create(move_vals)
self.write({'move_id': move.id, 'move_check': True})
created_moves |= move
@@ -618,12 +760,18 @@ class AccountAssetDepreciationLine(models.Model):
def post_lines_and_close_asset(self):
# we re-evaluate the assets to determine whether we can close them
+ # `message_post` invalidates the (whole) cache
+ # preprocess the assets and lines in which a message should be posted,
+ # and then post in batch will prevent the re-fetch of the same data over and over.
+ assets_to_close = self.env['account.asset.asset']
for line in self:
- line.log_message_when_posted()
asset = line.asset_id
if asset.currency_id.is_zero(asset.value_residual):
- asset.message_post(body=_("Document closed."))
- asset.write({'state': 'close'})
+ assets_to_close |= asset
+ self.log_message_when_posted()
+ assets_to_close.write({'state': 'close'})
+ for asset in assets_to_close:
+ asset.message_post(body=_("Document closed."))
def log_message_when_posted(self):
def _format_message(message_description, tracked_values):
@@ -635,15 +783,24 @@ class AccountAssetDepreciationLine(models.Model):
message += '%s' % values
return message
+ # `message_post` invalidates the (whole) cache
+ # preprocess the assets in which messages should be posted,
+ # and then post in batch will prevent the re-fetch of the same data over and over.
+ assets_to_post = {}
for line in self:
if line.move_id and line.move_id.state == 'draft':
partner_name = line.asset_id.partner_id.name
currency_name = line.asset_id.currency_id.name
- msg_values = {_('Currency'): currency_name, _('Amount'): line.amount}
+ msg_values = {_('Currency'): currency_name,
+ _('Amount'): line.amount}
if partner_name:
msg_values[_('Partner')] = partner_name
- msg = _format_message(_('Depreciation line posted.'), msg_values)
- line.asset_id.message_post(body=msg)
+ msg = _format_message(_('Depreciation line posted.'),
+ msg_values)
+ assets_to_post.setdefault(line.asset_id, []).append(msg)
+ for asset, messages in assets_to_post.items():
+ for msg in messages:
+ asset.message_post(body=msg)
def unlink(self):
for record in self:
diff --git a/base_accounting_kit/models/account_move.py b/base_accounting_kit/models/account_move.py
index 986b6f407..240e05a38 100644
--- a/base_accounting_kit/models/account_move.py
+++ b/base_accounting_kit/models/account_move.py
@@ -20,11 +20,14 @@
#
#############################################################################
+from datetime import datetime
+
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.addons.base.models import decimal_precision as dp
from odoo.exceptions import UserError
+from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
class AccountMove(models.Model):
@@ -35,6 +38,16 @@ class AccountMove(models.Model):
string='Assets Depreciation Lines',
ondelete="restrict")
+ def button_cancel(self):
+ for move in self:
+ for line in move.asset_depreciation_ids:
+ line.move_posted_check = False
+ return super(AccountMove, self).button_cancel()
+
+ def post(self):
+ self.mapped('asset_depreciation_ids').post_lines_and_close_asset()
+ return super(AccountMove, self).post()
+
@api.model
def _refund_cleanup_lines(self, lines):
result = super(AccountMove, self)._refund_cleanup_lines(lines)
@@ -63,26 +76,12 @@ class AccountMove(models.Model):
inv.invoice_line_ids.with_context(context).asset_create()
return result
- def button_cancel(self):
- for move in self:
- for line in move.asset_depreciation_ids:
- line.move_posted_check = False
- return super(AccountMove, self).button_cancel()
-
- def post(self):
- for move in self:
- for depreciation_line in move.asset_depreciation_ids:
- depreciation_line.post_lines_and_close_asset()
- return super(AccountMove, self).post()
-
-class AccountMoveLine(models.Model):
+class AccountInvoiceLine(models.Model):
_inherit = 'account.move.line'
asset_category_id = fields.Many2one('account.asset.category',
string='Asset Category')
- type_rel = fields.Selection(related='move_id.type')
- move_asset_category_id = fields.Many2one('account.move')
asset_start_date = fields.Date(string='Asset Start Date',
compute='_get_asset_date', readonly=True,
store=True)
@@ -90,8 +89,9 @@ class AccountMoveLine(models.Model):
compute='_get_asset_date', readonly=True,
store=True)
asset_mrr = fields.Float(string='Monthly Recurring Revenue',
- compute='_get_asset_date', readonly=True,
- digits=dp.get_precision('Account'), store=True)
+ compute='_get_asset_date',
+ readonly=True, digits=dp.get_precision('Account'),
+ store=True)
@api.depends('asset_category_id', 'move_id.invoice_date')
def _get_asset_date(self):
@@ -102,17 +102,18 @@ class AccountMoveLine(models.Model):
cat = record.asset_category_id
if cat:
if cat.method_number == 0 or cat.method_period == 0:
- raise UserError(_('The number of depreciations or '
- 'the period length of your asset category cannot be 0.'))
+ raise UserError(_(
+ 'The number of depreciations or the period length of your asset category cannot be null.'))
months = cat.method_number * cat.method_period
if record.move_id.type in ['out_invoice', 'out_refund']:
- record.asset_mrr = record.price_subtotal / months
+ record.asset_mrr = record.price_subtotal_signed / months
if record.move_id.invoice_date:
- start_date = record.move_id.invoice_date.replace(day=1)
+ start_date = datetime.strptime(
+ str(record.move_id.invoice_date), DF).replace(day=1)
end_date = (start_date + relativedelta(months=months,
days=-1))
- record.asset_start_date = start_date
- record.asset_end_date = end_date
+ record.asset_start_date = start_date.strftime(DF)
+ record.asset_end_date = end_date.strftime(DF)
def asset_create(self):
for record in self:
@@ -146,13 +147,13 @@ class AccountMoveLine(models.Model):
@api.onchange('uom_id')
def _onchange_uom_id(self):
- result = super(AccountMoveLine, self)._onchange_uom_id()
+ result = super(AccountInvoiceLine, self)._onchange_uom_id()
self.onchange_asset_category_id()
return result
@api.onchange('product_id')
def _onchange_product_id(self):
- vals = super(AccountMoveLine, self)._onchange_product_id()
+ vals = super(AccountInvoiceLine, self)._onchange_product_id()
if self.product_id:
if self.move_id.type == 'out_invoice':
self.asset_category_id = self.product_id.product_tmpl_id.deferred_revenue_category_id
@@ -167,11 +168,9 @@ class AccountMoveLine(models.Model):
elif invoice.type == 'in_invoice':
self.asset_category_id = self.product_id.product_tmpl_id.asset_category_id.id
self.onchange_asset_category_id()
- super(AccountMoveLine, self)._set_additional_fields(invoice)
+ super(AccountInvoiceLine, self)._set_additional_fields(invoice)
def get_invoice_line_account(self, type, product, fpos, company):
return product.asset_category_id.account_asset_id or super(
- AccountMoveLine, self).get_invoice_line_account(type,
- product,
- fpos,
- company)
+ AccountInvoiceLine, self).get_invoice_line_account(type, product,
+ fpos, company)
diff --git a/base_accounting_kit/models/product_template.py b/base_accounting_kit/models/product_template.py
index 4be9f8d0e..f5f5b5c81 100644
--- a/base_accounting_kit/models/product_template.py
+++ b/base_accounting_kit/models/product_template.py
@@ -20,20 +20,14 @@
#
#############################################################################
-from odoo import fields, models
+from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
- asset_category_id = fields.Many2one('account.asset.category',
- string='Asset Type',
- company_dependent=True,
- ondelete="restrict")
- deferred_revenue_category_id = fields.Many2one('account.asset.category',
- string='Deferred Revenue Type',
- company_dependent=True,
- ondelete="restrict")
+ asset_category_id = fields.Many2one('account.asset.category', string='Asset Type', company_dependent=True, ondelete="restrict")
+ deferred_revenue_category_id = fields.Many2one('account.asset.category', string='Deferred Revenue Type', company_dependent=True, ondelete="restrict")
def _get_asset_accounts(self):
res = super(ProductTemplate, self)._get_asset_accounts()
diff --git a/base_accounting_kit/report/account_asset_report.py b/base_accounting_kit/report/account_asset_report.py
index 456a86fa5..309986beb 100644
--- a/base_accounting_kit/report/account_asset_report.py
+++ b/base_accounting_kit/report/account_asset_report.py
@@ -1,27 +1,7 @@
# -*- coding: utf-8 -*-
-#############################################################################
-#
-# Cybrosys Technologies Pvt. Ltd.
-#
-# Copyright (C) 2019-TODAY Cybrosys Technologies()
-# Author: Cybrosys Techno Solutions()
-#
-# You can modify it under the terms of the GNU LESSER
-# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
-#
-# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
-# (LGPL v3) along with this program.
-# If not, see .
-#
-#############################################################################
-
-from odoo import fields, models, tools
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo import api, fields, models, tools
class AssetAssetReport(models.Model):
_name = "asset.asset.report"
@@ -31,28 +11,19 @@ class AssetAssetReport(models.Model):
name = fields.Char(string='Year', required=False, readonly=True)
date = fields.Date(readonly=True)
depreciation_date = fields.Date(string='Depreciation Date', readonly=True)
- asset_id = fields.Many2one('account.asset.asset', string='Asset',
- readonly=True)
- asset_category_id = fields.Many2one('account.asset.category',
- string='Asset category', readonly=True)
- partner_id = fields.Many2one('res.partner', string='Partner',
- readonly=True)
- state = fields.Selection(
- [('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')],
- string='Status', readonly=True)
- depreciation_value = fields.Float(string='Amount of Depreciation Lines',
- readonly=True)
- installment_value = fields.Float(string='Amount of Installment Lines',
- readonly=True)
+ asset_id = fields.Many2one('account.asset.asset', string='Asset', readonly=True)
+ asset_category_id = fields.Many2one('account.asset.category', string='Asset category', readonly=True)
+ partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
+ state = fields.Selection([('draft', 'Draft'), ('open', 'Running'), ('close', 'Close')], string='Status', readonly=True)
+ depreciation_value = fields.Float(string='Amount of Depreciation Lines', readonly=True)
+ installment_value = fields.Float(string='Amount of Installment Lines', readonly=True)
move_check = fields.Boolean(string='Posted', readonly=True)
- installment_nbr = fields.Integer(string='Installment Count', readonly=True)
- depreciation_nbr = fields.Integer(string='Depreciation Count',
- readonly=True)
+ installment_nbr = fields.Integer(string='# of Installment Lines', readonly=True)
+ depreciation_nbr = fields.Integer(string='# of Depreciation Lines', readonly=True)
gross_value = fields.Float(string='Gross Amount', readonly=True)
posted_value = fields.Float(string='Posted Amount', readonly=True)
unposted_value = fields.Float(string='Unposted Amount', readonly=True)
- company_id = fields.Many2one('res.company', string='Company',
- readonly=True)
+ company_id = fields.Many2one('res.company', string='Company', readonly=True)
def init(self):
tools.drop_view_if_exists(self._cr, 'asset_asset_report')
diff --git a/base_accounting_kit/report/account_asset_report_views.xml b/base_accounting_kit/report/account_asset_report_views.xml
index af8370a63..b9cbea4fe 100644
--- a/base_accounting_kit/report/account_asset_report_views.xml
+++ b/base_accounting_kit/report/account_asset_report_views.xml
@@ -12,7 +12,6 @@
-
asset.asset.report.graph
asset.asset.report
@@ -34,6 +33,7 @@
+
@@ -60,21 +60,18 @@
Assets Analysis
asset.asset.report
graph,pivot
+
[('asset_category_id.type', '=', 'purchase')]
- {}
+ {'search_default_only_active': 1}
-
- No content
-
+
From this report, you can have an overview on all depreciations. The
search bar can also be used to personalize your assets depreciation reporting.
-
+ parent="account.account_reports_management_menu" sequence="21"/>
diff --git a/base_accounting_kit/report/cash_flow_report.xml b/base_accounting_kit/report/cash_flow_report.xml
index d0b7a849a..3dcc1637d 100644
--- a/base_accounting_kit/report/cash_flow_report.xml
+++ b/base_accounting_kit/report/cash_flow_report.xml
@@ -22,14 +22,14 @@
-
-
+
Name
- Debit
- Credit
+ Debit
+ Credit
Balance
+
@@ -42,60 +42,21 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
-
- Name
- Balance
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Name
- Balance
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
diff --git a/base_accounting_kit/security/account_asset_security.xml b/base_accounting_kit/security/account_asset_security.xml
index df01a4a26..02320b922 100644
--- a/base_accounting_kit/security/account_asset_security.xml
+++ b/base_accounting_kit/security/account_asset_security.xml
@@ -15,12 +15,5 @@
['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
-
- Accountant
-
-
-
-
-
diff --git a/base_accounting_kit/static/description/index.html b/base_accounting_kit/static/description/index.html
index dcd120766..51e187786 100644
--- a/base_accounting_kit/static/description/index.html
+++ b/base_accounting_kit/static/description/index.html
@@ -55,12 +55,6 @@
style="font-size: 1.05rem;font-weight: 400;transition: all .15s ease;color: #d31c22;background-color: #d31c22;box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08);border: 0;font-family: 'Open Sans',sans-serif;width: 140px;border-radius: 0.30rem;">
Screenshots
-
-
- Overview
@@ -68,7 +62,11 @@
aria-controls="pills-home" aria-selected="true" class="nav-link " style="color: #000000;line-height: 33px;border: 0;border-radius: .25rem;font-weight: 400; text-align: center;
color: #fff;">Features
-
+
+ Screenshots
@@ -83,10 +81,88 @@
style="padding-top: 30px; padding-bottom: 30px; padding: 30px;">
-
-
-
-
+
+
Overview
+
+
+ This module will bring back the accounting features such as Account Reports, Asset Management
+ and Customer Follow Up into Odoo 13 Community Edition. Also new features are added to the
+ accounting module such as Customer Credit Limit, Recurring Payment, PDC Management and Lock Dates.
+
+
+
+
+
+
+
+
+
+
Screenshots
@@ -485,91 +561,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
Overview
-
-
- This module will bring back the accounting features such as Account Reports, Asset Management
- and Customer Follow Up into Odoo 13 Community Edition. Also new features are added to the
- accounting module such as Customer Credit Limit, Recurring Payment, PDC Management and Lock Dates.
-
-
-
diff --git a/base_accounting_kit/static/src/js/account_asset.js b/base_accounting_kit/static/src/js/account_asset.js
index 99de3180b..a60c8b63e 100644
--- a/base_accounting_kit/static/src/js/account_asset.js
+++ b/base_accounting_kit/static/src/js/account_asset.js
@@ -1,4 +1,4 @@
-odoo.define('om_account_asset.widget', function(require) {
+odoo.define('base_accounting_kit.account_asset', function(require) {
"use strict";
/**
@@ -58,7 +58,7 @@ var AccountAssetWidget = AbstractField.extend({
type: 'button',
title: title,
disabled: disabled,
- }).addClass('btn btn-link fa fa-circle o_deprec_lines_toggler ' + className);
+ }).addClass('btn btn-sm btn-link fa fa-circle o_deprec_lines_toggler ' + className);
this.$el.html($button);
},
diff --git a/base_accounting_kit/static/src/less/account_asset.less b/base_accounting_kit/static/src/less/account_asset.less
new file mode 100644
index 000000000..672317f74
--- /dev/null
+++ b/base_accounting_kit/static/src/less/account_asset.less
@@ -0,0 +1,9 @@
+.o_web_client .o_deprec_lines_toggler {
+ color: #b52121;
+ &.o_is_posted {
+ color: #6f7370;
+ }
+ &.o_unposted {
+ color: #178230;
+ }
+}
diff --git a/base_accounting_kit/static/src/scss/account_asset.scss b/base_accounting_kit/static/src/scss/account_asset.scss
deleted file mode 100644
index bff97fa20..000000000
--- a/base_accounting_kit/static/src/scss/account_asset.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.o_web_client .o_deprec_lines_toggler {
- color: theme-color('danger');
- &.o_is_posted {
- color: theme-color('success');
- }
- &.o_unposted {
- color: theme-color('warning');
- }
-}
diff --git a/base_accounting_kit/views/account_asset_templates.xml b/base_accounting_kit/views/account_asset_templates.xml
index c8cfabee5..df9b56962 100644
--- a/base_accounting_kit/views/account_asset_templates.xml
+++ b/base_accounting_kit/views/account_asset_templates.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/base_accounting_kit/views/account_asset_views.xml b/base_accounting_kit/views/account_asset_views.xml
index f1e1fccb1..b626af1e2 100644
--- a/base_accounting_kit/views/account_asset_views.xml
+++ b/base_accounting_kit/views/account_asset_views.xml
@@ -1,6 +1,10 @@
+
+
account.asset.category.form
account.asset.category
@@ -16,40 +20,27 @@
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
-
+
+
@@ -64,7 +55,6 @@
-
@@ -89,11 +79,11 @@
-
+
-
@@ -117,24 +107,24 @@
-
- account.asset.category.search
- account.asset.category
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- account_asset_asset_form
+
+ account.asset.asset.form
account.asset.asset
-
+
-
-
-
@@ -176,8 +162,7 @@
-
-
+
@@ -185,14 +170,14 @@
-
+
-