forked from OCA/account-financial-tools
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathaccount_asset_profile.py
241 lines (229 loc) · 9.2 KB
/
account_asset_profile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class AccountAssetProfile(models.Model):
_name = "account.asset.profile"
_inherit = "analytic.mixin"
_check_company_auto = True
_description = "Asset profile"
_order = "name"
name = fields.Char(size=64, required=True, index=True)
note = fields.Text()
account_asset_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Asset Account",
check_company=True,
required=True,
)
account_depreciation_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Depreciation Account",
check_company=True,
required=True,
)
account_expense_depreciation_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
string="Depr. Expense Account",
check_company=True,
required=True,
)
account_plus_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Plus-Value Account",
)
account_min_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Min-Value Account",
)
account_residual_value_id = fields.Many2one(
comodel_name="account.account",
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]",
check_company=True,
string="Residual Value Account",
)
journal_id = fields.Many2one(
comodel_name="account.journal",
domain="[('type', '=', 'general'), ('company_id', '=', company_id)]",
string="Journal",
check_company=True,
required=True,
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self._default_company_id(),
)
group_ids = fields.Many2many(
comodel_name="account.asset.group",
relation="account_asset_profile_group_rel",
column1="profile_id",
column2="group_id",
check_company=True,
string="Asset Groups",
)
salvage_value = fields.Float(
digits="Account",
help="The estimated value that an asset will realize upon "
"its sale at the end of its useful life.\n"
"This value is used to determine the depreciation amounts.",
)
salvage_type = fields.Selection(
selection=[("fixed", "Fixed"), ("percent", "Percentage of Price")]
)
method = fields.Selection(
selection=lambda self: self._selection_method(),
string="Computation Method",
required=True,
help="Choose the method to use to compute the depreciation lines.\n"
" * Linear: Calculated on basis of: "
"Depreciation Base / Number of Depreciations. "
"Depreciation Base = Purchase Value - Salvage Value.\n"
" * Linear-Limit: Linear up to Salvage Value. "
"Depreciation Base = Purchase Value.\n"
" * Degressive: Calculated on basis of: "
"Residual Value * Degressive Factor.\n"
" * Degressive-Linear (only for Time Method = Year): "
"Degressive becomes linear when the annual linear "
"depreciation exceeds the annual degressive depreciation.\n"
" * Degressive-Limit: Degressive up to Salvage Value. "
"The Depreciation Base is equal to the asset value.",
default="linear",
)
method_number = fields.Integer(
string="Number of Years",
help="The number of years needed to depreciate your asset",
default=5,
)
method_period = fields.Selection(
selection=lambda self: self._selection_method_period(),
string="Period Length",
required=True,
default="year",
help="Period length for the depreciation accounting entries",
)
method_progress_factor = fields.Float(string="Degressive Factor", default=0.3)
method_time = fields.Selection(
selection=lambda self: self._selection_method_time(),
string="Time Method",
required=True,
default="year",
help="Choose the method to use to compute the dates and "
"number of depreciation lines.\n"
" * Number of Years: Specify the number of years "
"for the depreciation.\n"
" * Number of Depreciations: Fix the number of "
"depreciation lines and the time between 2 depreciations.\n",
)
days_calc = fields.Boolean(
string="Calculate by days",
default=False,
help="Use number of days to calculate depreciation amount",
)
use_leap_years = fields.Boolean(
default=False,
help="If not set, the system will distribute evenly the amount to "
"amortize across the years, based on the number of years. "
"So the amount per year will be the "
"depreciation base / number of years.\n "
"If set, the system will consider if the current year "
"is a leap year. The amount to depreciate per year will be "
"calculated as depreciation base / (depreciation end date - "
"start date + 1) * days in the current year.",
)
prorata = fields.Boolean(
string="Prorata Temporis",
compute="_compute_prorrata",
readonly=False,
store=True,
help="Indicates that the first depreciation entry for this asset "
"has to be done from the depreciation start date instead of "
"the first day of the fiscal year.",
)
open_asset = fields.Boolean(
string="Skip Draft State",
help="Check this if you want to automatically confirm the assets "
"of this profile when created by invoices.",
)
asset_product_item = fields.Boolean(
string="Create an asset by product item",
help="By default during the validation of an invoice, an asset "
"is created by invoice line as long as an accounting entry is "
"created by invoice line. "
"With this setting, an accounting entry will be created by "
"product item. So, there will be an asset by product item.",
)
active = fields.Boolean(default=True)
allow_reversal = fields.Boolean(
"Allow Reversal of journal entries",
help="If set, when pressing the Delete/Reverse Move button in a "
"posted depreciation line will prompt the option to reverse the "
"journal entry, instead of deleting them.",
)
@api.model
def _default_company_id(self):
return self.env.company
@api.model
def _selection_method(self):
return [
("linear", _("Linear")),
("linear-limit", _("Linear up to Salvage Value")),
("degressive", _("Degressive")),
("degr-linear", _("Degressive-Linear")),
("degr-limit", _("Degressive up to Salvage Value")),
]
@api.model
def _selection_method_period(self):
return [("month", _("Month")), ("quarter", _("Quarter")), ("year", _("Year"))]
@api.model
def _selection_method_time(self):
return [
("year", _("Number of Years or end date")),
("number", _("Number of Depreciations")),
]
@api.constrains("method", "method_time")
def _check_method(self):
if any(a.method == "degr-linear" and a.method_time != "year" for a in self):
raise UserError(
_("Degressive-Linear is only supported for Time Method = Year.")
)
@api.depends("method_time")
def _compute_prorrata(self):
for profile in self:
if profile.method_time != "year":
profile.prorata = True
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get("method_time") != "year" and not vals.get("prorata"):
vals["prorata"] = True
profile_ids = super().create(vals_list)
account_dict = {}
for profile_id in profile_ids.filtered(
lambda x: not x.account_asset_id.asset_profile_id
):
account_dict.setdefault(profile_id.account_asset_id, []).append(
profile_id.id
)
for account, profile_list in account_dict.items():
account.write({"asset_profile_id": profile_list[-1]})
return profile_ids
def write(self, vals):
if vals.get("method_time"):
if vals["method_time"] != "year" and not vals.get("prorata"):
vals["prorata"] = True
res = super().write(vals)
# TODO last profile in self is defined as default on the related
# account. must be improved.
account = self.env["account.account"].browse(vals.get("account_asset_id"))
if self and account and not account.asset_profile_id:
account.write({"asset_profile_id": self[-1].id})
return res