Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
===================
Asset Force Account
===================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:3e14f5186e43cd32b87daa834fc648444b45cb582b9167f9cb9acf03ec5ce22f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github
:target: https://github.com/OCA/account-financial-tools/tree/18.0/account_asset_force_account
:alt: OCA/account-financial-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/account-financial-tools-18-0/account-financial-tools-18-0-account_asset_force_account
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module enables the ability to override default accounts directly
from the asset form.
**Table of contents**
.. contents::
:local:
Usage
=====
1. | **Create an Asset Profile**:
| Navigate to **Configuration -> Asset Profiles** and create a new
profile.
2. **Create a Vendor Bill**:
- Go to **Vendors -> Bills** and create a new bill.
- Add a product and select the asset profile you just created.
- The Asset Account will be derived from the profile or can be
manually updated at this step (the invoice account will be used as
the Asset Account).
- Set the product price and confirm the bill.
3. | **Asset Creation**:
| Once the bill is confirmed, the asset will be created and populated
with the associated accounts. You can now manually adjust the
**Depreciation Account** and **Depreciation Expense Account** if
necessary.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-financial-tools/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/account-financial-tools/issues/new?body=module:%20account_asset_force_account%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Bernat Obrador (APSL-Nagarro)
Contributors
------------
- `APSL-Nagarro <https://apsl.tech>`__:
- Bernat Obrador <bobrador@apsl.net>
- `Heliconia Solutions Pvt. Ltd. <https://www.heliconia.io>`__
- Bhavesh Heliconia
Maintainers
-----------
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-BernatObrador| image:: https://github.com/BernatObrador.png?size=40px
:target: https://github.com/BernatObrador
:alt: BernatObrador
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-BernatObrador|
This module is part of the `OCA/account-financial-tools <https://github.com/OCA/account-financial-tools/tree/18.0/account_asset_force_account>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models

View File

@@ -0,0 +1,19 @@
# Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Asset Force Account",
"version": "18.0.1.0.0",
"website": "https://github.com/OCA/account-financial-tools",
"author": "Bernat Obrador (APSL-Nagarro), Odoo Community Association (OCA)",
"category": "Accounting & Finance",
"maintainers": ["BernatObrador"],
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"account_asset_management",
],
"data": [
"views/account_asset.xml",
],
}

View File

@@ -0,0 +1,59 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_force_account
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset
msgid "Asset"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_asset_id
msgid "Asset Account"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset_line
msgid "Asset depreciation table line"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "Depreciation Account"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "Depreciation Expense Account"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "The account used to record depreciation for the asset."
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "The account used to record the expense of the depreciation."
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_asset_id
msgid "The account used to record the value of the asset."
msgstr ""

View File

@@ -0,0 +1,62 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_force_accounts
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-09-18 09:41+0000\n"
"PO-Revision-Date: 2024-09-18 09:41+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset
msgid "Asset"
msgstr "Actiu"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_asset_id
msgid "Asset Account"
msgstr "Compte de l'actiu"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset_line
msgid "Asset depreciation table line"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "Depreciation Account"
msgstr "Compte d'amortització"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "Depreciation Expense Account"
msgstr "Compte de despeses d'amortització"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "The account used to record depreciation for the asset."
msgstr "El compte utilitzat per registrar l'amortització de l'actiu."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "The account used to record the expense of the depreciation."
msgstr "El compte utilitzat per registrar la despesa per amortització."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_asset_id
msgid "The account used to record the value of the asset."
msgstr "El compte utilitzat per registrar el valor de l'actiu."

View File

@@ -0,0 +1,62 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_force_accounts
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-09-18 09:43+0000\n"
"PO-Revision-Date: 2024-09-18 09:43+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset
msgid "Asset"
msgstr "Activo"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_asset_id
msgid "Asset Account"
msgstr "Cuenta de activo"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset_line
msgid "Asset depreciation table line"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "Depreciation Account"
msgstr "Cuenta de amortización"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "Depreciation Expense Account"
msgstr "Cuenta de gastos de amortización"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "The account used to record depreciation for the asset."
msgstr "La cuenta utilizada para registrar la depreciación del activo."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "The account used to record the expense of the depreciation."
msgstr "La cuenta utilizada para registrar el gasto por depreciación."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_asset_id
msgid "The account used to record the value of the asset."
msgstr "La cuenta utilizada para registrar el valor del activo."

View File

@@ -0,0 +1,62 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_force_account
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-28 17:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.6.2\n"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset
msgid "Asset"
msgstr "Cespite"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_asset_id
msgid "Asset Account"
msgstr "Conto cespite"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_asset_line
msgid "Asset depreciation table line"
msgstr "Riga tabella ammortamenti cespite"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "Depreciation Account"
msgstr "Conto amm.to"
#. module: account_asset_force_account
#: model:ir.model.fields,field_description:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "Depreciation Expense Account"
msgstr "Conto spese amm.to"
#. module: account_asset_force_account
#: model:ir.model,name:account_asset_force_account.model_account_move_line
msgid "Journal Item"
msgstr "Movimento contabile"
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_depreciation_id
msgid "The account used to record depreciation for the asset."
msgstr "Il conto utilizzato per registrare l'ammortamento per un cespite."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_expense_depreciation_id
msgid "The account used to record the expense of the depreciation."
msgstr "Il conto utilizzato per registrare le spese dell'ammortamento."
#. module: account_asset_force_account
#: model:ir.model.fields,help:account_asset_force_account.field_account_asset__account_asset_id
msgid "The account used to record the value of the asset."
msgstr "Il conto utilizzato per registrare il valore del cespite."

View File

@@ -0,0 +1,3 @@
from . import account_asset
from . import account_asset_line
from . import account_move_line

View File

@@ -0,0 +1,72 @@
# Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AccountAsset(models.Model):
_inherit = "account.asset"
account_asset_id = fields.Many2one(
comodel_name="account.account",
string="Asset Account",
compute="_compute_account_asset_id",
help="The account used to record the value of the asset.",
store=True,
)
account_depreciation_id = fields.Many2one(
comodel_name="account.account",
string="Depreciation Account",
domain="[('deprecated', '=', False), ('company_ids', '=', company_id)]",
help="The account used to record depreciation for the asset.",
required=True,
)
account_expense_depreciation_id = fields.Many2one(
comodel_name="account.account",
string="Depreciation Expense Account",
domain="[('deprecated', '=', False), ('company_ids', '=', company_id)]",
help="The account used to record the expense of the depreciation.",
required=True,
)
@api.onchange("profile_id")
def _onchange_profile_id(self):
# To avoid changes when the asset is confirmed
if self.profile_id and self.state == "draft":
self.account_depreciation_id = self.profile_id.account_depreciation_id
self.account_expense_depreciation_id = (
self.profile_id.account_expense_depreciation_id
)
self._compute_account_asset_id()
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get("profile_id"):
profile = self.env["account.asset.profile"].browse(vals["profile_id"])
if not vals.get("account_depreciation_id"):
vals["account_depreciation_id"] = profile.account_depreciation_id.id
if not vals.get("account_expense_depreciation_id"):
vals["account_expense_depreciation_id"] = (
profile.account_expense_depreciation_id.id
)
return super().create(vals_list)
@api.depends("account_move_line_ids", "profile_id")
def _compute_account_asset_id(self):
for record in self:
# Cannot update the account_asset_id if the asset is not in draft state
if record.state != "draft":
continue
# Looks if the asset comes from an invoice, if so, takes the account
# from the invoice
if len(record.account_move_line_ids.account_id) != 0:
invoice_line = record.account_move_line_ids.filtered(
lambda line: line.move_id.move_type == "in_invoice"
)
if invoice_line:
record.account_asset_id = invoice_line.account_id
continue
# If not, takes the account from the profile
record.account_asset_id = record.profile_id.account_asset_id

View File

@@ -0,0 +1,17 @@
# Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class AccountAssetLine(models.Model):
_inherit = "account.asset.line"
def _setup_move_line_data(self, depreciation_date, account, ml_type, move):
res = super()._setup_move_line_data(depreciation_date, account, ml_type, move)
asset = self.asset_id
if ml_type == "depreciation" and asset.account_depreciation_id:
res["account_id"] = asset.account_depreciation_id.id
if ml_type == "expense" and asset.account_expense_depreciation_id:
res["account_id"] = asset.account_expense_depreciation_id.id
return res

View File

@@ -0,0 +1,13 @@
# Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, models
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
@api.onchange("asset_profile_id")
def _onchange_asset_profile_id(self):
if self.account_id and self.account_id.account_type == "asset_fixed":
return
super()._onchange_asset_profile_id()

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,4 @@
- [APSL-Nagarro](<https://apsl.tech>):
- Bernat Obrador \<<bobrador@apsl.net>\>
- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io)
- Bhavesh Heliconia

View File

@@ -0,0 +1 @@
This module enables the ability to override default accounts directly from the asset form.

View File

@@ -0,0 +1,11 @@
1. **Create an Asset Profile**:
Navigate to **Configuration -> Asset Profiles** and create a new profile.
2. **Create a Vendor Bill**:
- Go to **Vendors -> Bills** and create a new bill.
- Add a product and select the asset profile you just created.
- The Asset Account will be derived from the profile or can be manually updated at this step (the invoice account will be used as the Asset Account).
- Set the product price and confirm the bill.
3. **Asset Creation**:
Once the bill is confirmed, the asset will be created and populated with the associated accounts. You can now manually adjust the **Depreciation Account** and **Depreciation Expense Account** if necessary.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,469 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="asset-force-account">
<h1>Asset Force Account</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:3e14f5186e43cd32b87daa834fc648444b45cb582b9167f9cb9acf03ec5ce22f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-financial-tools/tree/18.0/account_asset_force_account"><img alt="OCA/account-financial-tools" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-financial-tools-18-0/account-financial-tools-18-0-account_asset_force_account"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module enables the ability to override default accounts directly
from the asset form.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<ol class="arabic">
<li><div class="first line-block">
<div class="line"><strong>Create an Asset Profile</strong>:</div>
<div class="line">Navigate to <strong>Configuration -&gt; Asset Profiles</strong> and create a new
profile.</div>
</div>
</li>
<li><p class="first"><strong>Create a Vendor Bill</strong>:</p>
<ul class="simple">
<li>Go to <strong>Vendors -&gt; Bills</strong> and create a new bill.</li>
<li>Add a product and select the asset profile you just created.</li>
<li>The Asset Account will be derived from the profile or can be
manually updated at this step (the invoice account will be used as
the Asset Account).</li>
<li>Set the product price and confirm the bill.</li>
</ul>
</li>
<li><div class="first line-block">
<div class="line"><strong>Asset Creation</strong>:</div>
<div class="line">Once the bill is confirmed, the asset will be created and populated
with the associated accounts. You can now manually adjust the
<strong>Depreciation Account</strong> and <strong>Depreciation Expense Account</strong> if
necessary.</div>
</div>
</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-financial-tools/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/account-financial-tools/issues/new?body=module:%20account_asset_force_account%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
<ul class="simple">
<li>Bernat Obrador (APSL-Nagarro)</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://apsl.tech">APSL-Nagarro</a>:<ul>
<li>Bernat Obrador &lt;<a class="reference external" href="mailto:bobrador&#64;apsl.net">bobrador&#64;apsl.net</a>&gt;</li>
</ul>
</li>
<li><a class="reference external" href="https://www.heliconia.io">Heliconia Solutions Pvt. Ltd.</a><ul>
<li>Bhavesh Heliconia</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/BernatObrador"><img alt="BernatObrador" src="https://github.com/BernatObrador.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-financial-tools/tree/18.0/account_asset_force_account">OCA/account-financial-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1 @@
from . import test_account_asset_management_force_account

View File

@@ -0,0 +1,240 @@
# Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import time
from odoo.tests import tagged
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
@tagged("post_install", "-at_install")
class TestAssetManagement(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.asset_model = cls.env["account.asset"]
cls.asset_profile_model = cls.env["account.asset.profile"]
cls.account_depreciation_car = cls.env["account.account"].create(
{
"name": "Fixed Asset - Vehicle",
"code": "151001",
"account_type": "asset_fixed",
}
)
cls.account_expense_laptop = cls.env["account.account"].create(
{
"name": "Depreciation Expense Account - Laptop",
"code": "600011",
"account_type": "expense",
}
)
# Asset Profile 1
cls.ict3Y = cls.asset_profile_model.create(
{
"account_expense_depreciation_id": cls.company_data[
"default_account_expense"
].id,
"account_asset_id": cls.company_data["default_account_assets"].id,
"account_depreciation_id": cls.company_data[
"default_account_assets"
].id,
"journal_id": cls.company_data["default_journal_purchase"].id,
"name": "Hardware - 3 Years",
"method_time": "year",
"method_number": 3,
"method_period": "year",
}
)
# Asset Profile 2
cls.car5y = cls.asset_profile_model.create(
{
"account_expense_depreciation_id": cls.company_data[
"default_account_expense"
].id,
"account_asset_id": cls.company_data["default_account_assets"].id,
"account_depreciation_id": cls.company_data[
"default_account_assets"
].id,
"journal_id": cls.company_data["default_journal_purchase"].id,
"name": "Cars - 5 Years",
"method_time": "year",
"method_number": 5,
"method_period": "year",
}
)
def test_change_asset_accounts(self):
ict0 = self.asset_model.create(
{
"name": "test asset",
"profile_id": self.ict3Y.id,
"purchase_value": 1500,
"date_start": "1901-02-01",
"method_time": "year",
"method_number": 3,
"method_period": "year",
"account_depreciation_id": self.ict3Y.account_depreciation_id.id,
"account_expense_depreciation_id": self.account_expense_laptop.id,
}
)
self.assertEqual(ict0.state, "draft")
self.assertEqual(ict0.purchase_value, 1500)
self.assertEqual(ict0.salvage_value, 0)
self.assertEqual(ict0.depreciation_base, 1500)
self.assertEqual(len(ict0.depreciation_line_ids), 1)
self.assertEqual(ict0.account_asset_id.id, ict0.profile_id.account_asset_id.id)
self.assertEqual(
ict0.account_depreciation_id.id, ict0.profile_id.account_depreciation_id.id
)
self.assertEqual(
ict0.account_expense_depreciation_id.id, self.account_expense_laptop.id
)
aed_id = self.car5y.account_expense_depreciation_id.id
vehicle0 = self.asset_model.create(
{
"state": "draft",
"method_time": "year",
"method_number": 5,
"method_period": "year",
"name": "CEO's Car",
"purchase_value": 12000.0,
"salvage_value": 2000.0,
"profile_id": self.car5y.id,
"date_start": time.strftime("%Y-01-01"),
"account_depreciation_id": self.account_depreciation_car.id,
"account_expense_depreciation_id": aed_id,
}
)
self.assertEqual(vehicle0.state, "draft")
self.assertEqual(vehicle0.purchase_value, 12000)
self.assertEqual(vehicle0.salvage_value, 2000)
self.assertEqual(vehicle0.depreciation_base, 10000)
self.assertEqual(len(vehicle0.depreciation_line_ids), 1)
self.assertEqual(
vehicle0.account_asset_id.id, vehicle0.profile_id.account_asset_id.id
)
self.assertEqual(
vehicle0.account_depreciation_id.id, self.account_depreciation_car.id
)
self.assertEqual(
vehicle0.account_expense_depreciation_id.id,
vehicle0.profile_id.account_expense_depreciation_id.id,
)
ict0.compute_depreciation_board()
ict0.invalidate_recordset()
self.assertEqual(len(ict0.depreciation_line_ids), 4)
self.assertEqual(ict0.depreciation_line_ids[1].amount, 500)
vehicle0.compute_depreciation_board()
vehicle0.invalidate_recordset()
self.assertEqual(len(vehicle0.depreciation_line_ids), 6)
self.assertEqual(vehicle0.depreciation_line_ids[1].amount, 2000)
ict0.validate()
ict0_created_moves_ids = ict0.depreciation_line_ids[1].create_move()
ict0.invalidate_recordset()
for move_id in ict0_created_moves_ids:
move = self.env["account.move"].browse(move_id)
# Validate that the profile account is used
depr_line = move.line_ids.filtered(
lambda line: line.account_id == self.ict3Y.account_depreciation_id
)
self.assertTrue(depr_line)
# Validate that the forced expense depreciation account is being used
expense_line = move.line_ids.filtered(
lambda line: line.account_id == self.account_expense_laptop
)
self.assertTrue(expense_line)
# Check that the asset is now open and depreciation is posted correctly
self.assertEqual(ict0.state, "open")
self.assertEqual(ict0.value_depreciated, 500)
self.assertEqual(ict0.value_residual, 1000)
vehicle0.validate()
vehicle0_created_move_ids = vehicle0.depreciation_line_ids[1].create_move()
for move_id in vehicle0_created_move_ids:
move = self.env["account.move"].browse(move_id)
# Validate that the forced depreciation account is being used
depr_line = move.line_ids.filtered(
lambda line: line.account_id == self.account_depreciation_car
)
self.assertTrue(depr_line)
# Validate that the profile account is used
expense_line = move.line_ids.filtered(
lambda line: line.account_id
== self.car5y.account_expense_depreciation_id
)
self.assertTrue(expense_line)
vehicle0.invalidate_recordset()
# Ensure the asset's state and values are correct after depreciation posting
self.assertEqual(vehicle0.state, "open")
self.assertEqual(vehicle0.value_depreciated, 2000)
self.assertEqual(vehicle0.value_residual, 8000)
vehicle0.invalidate_recordset()
def test_profile_onchange_and_compute_account_asset_id_from_invoice(self):
# Create asset with non-draft state → onchange should do nothing
aed_id = self.ict3Y.account_expense_depreciation_id.id
asset = self.asset_model.create(
{
"name": "Non-Draft Asset",
"profile_id": self.ict3Y.id,
"purchase_value": 1000,
"date_start": "2025-01-01",
"method_time": "year",
"method_number": 1,
"method_period": "year",
"account_depreciation_id": self.ict3Y.account_depreciation_id.id,
"account_expense_depreciation_id": aed_id,
"state": "open",
}
)
# Trigger onchange and ensure fields remain unchanged
asset._onchange_profile_id()
self.assertEqual(
asset.account_depreciation_id.id, self.ict3Y.account_depreciation_id.id
)
def test_create_fallback_to_profile_accounts(self):
asset = self.asset_model.create(
{
"name": "Profile Only Asset",
"profile_id": self.ict3Y.id,
"purchase_value": 500,
"date_start": "2025-01-01",
"method_time": "year",
"method_number": 1,
"method_period": "year",
}
)
self.assertEqual(
asset.account_depreciation_id.id, self.ict3Y.account_depreciation_id.id
)
self.assertEqual(
asset.account_expense_depreciation_id.id,
self.ict3Y.account_expense_depreciation_id.id,
)
def test_onchange_asset_profile_id_no_super_called_if_asset_fixed(self):
move_line = self.env["account.move.line"].new(
{
"account_id": self.account_depreciation_car.id,
}
)
move_line._onchange_asset_profile_id()
self.assertEqual(move_line.account_id.account_type, "asset_fixed")

View File

@@ -0,0 +1,28 @@
<?xml version='1.0' encoding='utf-8' ?>
<!-- # Copyright 2024 Bernat Obrador(APSL-Nagarro)<bobrador@apsl.net>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="account_asset_view_form_inherit" model="ir.ui.view">
<field name="name">account.asset.form.inherit</field>
<field name="model">account.asset</field>
<field
name="inherit_id"
ref="account_asset_management.account_asset_view_form"
/>
<field name="arch" type="xml">
<xpath expr="//field[@name='group_ids']" position="after">
<field name="account_asset_id" invisible="not profile_id" />
<field
name="account_depreciation_id"
readonly="state in ['open', 'close', 'removed']"
invisible="not profile_id"
/>
<field
name="account_expense_depreciation_id"
readonly="state in ['open', 'close', 'removed']"
invisible="not profile_id"
/>
</xpath>
</field>
</record>
</odoo>