Skip to content

Commit a954d49

Browse files
committed
Merge PR OCA#1021 into 14.0
Signed-off-by kittiu
2 parents e68345c + e4c73e9 commit a954d49

File tree

34 files changed

+516
-0
lines changed

34 files changed

+516
-0
lines changed

Diff for: account_move_line_accounting_description/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import models
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
{
5+
"name": "Acccount Move Accounting Description",
6+
"version": "14.0.1.0.0",
7+
"summary": "Adds an 'accounting description' on products",
8+
"author": "Camptocamp, Odoo Community Association (OCA)",
9+
"website": "https://github.com/OCA/account-invoicing",
10+
"license": "AGPL-3",
11+
"category": "Accounting & Finance",
12+
"depends": ["account", "product"],
13+
"data": [
14+
"views/product_template.xml",
15+
"views/account_move.xml",
16+
"reports/invoice.xml",
17+
],
18+
"installable": True,
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import product
5+
from . import account_move
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo import api, fields, models
5+
6+
7+
class AccountMoveLine(models.Model):
8+
_inherit = "account.move.line"
9+
10+
external_name = fields.Char(string="External Name")
11+
12+
@api.onchange("product_id")
13+
def _onchange_product_id(self):
14+
super()._onchange_product_id()
15+
for line in self:
16+
line.external_name = line.name
17+
if line.product_id.accounting_description:
18+
line.name = line.product_id.accounting_description
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo import fields, models
5+
6+
7+
class ProductTemplate(models.Model):
8+
_inherit = "product.template"
9+
10+
accounting_description = fields.Text(string="Accounting description")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Anna Janiszewska <[email protected]>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This module adds:
2+
- accounting description on product to use instead of product name on the invoice.
3+
- external name on account move to keep original product's name on invoice report
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo>
3+
<template id="report_invoice_document" inherit_id="account.report_invoice_document">
4+
<xpath
5+
expr="//td[@name='account_invoice_line_name']//span[@t-field='line.name']"
6+
position="replace"
7+
>
8+
<span t-field="line.external_name" t-options="{'widget': 'text'}" />
9+
</xpath>
10+
</template>
11+
</odoo>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import test_account_move_line_description
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo.tests import Form
5+
from odoo.tests.common import SavepointCase
6+
7+
8+
class TestAccountLineDescription(SavepointCase):
9+
@classmethod
10+
def setUpClass(cls):
11+
super().setUpClass()
12+
cls.partner_1 = cls.env.ref("base.res_partner_1")
13+
cls.product_with_acc_desc = cls.env.ref("product.product_product_1")
14+
cls.product_without_acc_desc = cls.env.ref("product.product_product_2")
15+
16+
consumable_cat = cls.env["product.category"].search(
17+
[("name", "=", "Consumable")]
18+
)
19+
20+
cls.product_with_acc_desc.categ_id = consumable_cat
21+
cls.product_without_acc_desc.categ_id = consumable_cat
22+
23+
cls.product_with_acc_desc.accounting_description = "Product1_acc_desc"
24+
25+
cls.account_move = cls.env["account.move"]
26+
27+
def test_invoice_line_with_accounting_description(self):
28+
invoice_form_acc_desc = Form(
29+
self.account_move.with_context(default_move_type="out_invoice")
30+
)
31+
invoice_form_acc_desc.partner_id = self.partner_1
32+
33+
with invoice_form_acc_desc.invoice_line_ids.new() as line_form:
34+
line_form.product_id = self.product_with_acc_desc
35+
line_form.quantity = 1
36+
line_form.price_unit = 2.99
37+
38+
self.invoice_acc_desc = invoice_form_acc_desc.save()
39+
inv_line_with_product = self.invoice_acc_desc.invoice_line_ids.filtered(
40+
lambda x: x.product_id
41+
)
42+
self.assertTrue(self.product_with_acc_desc.accounting_description)
43+
self.assertEqual(
44+
inv_line_with_product.name,
45+
self.product_with_acc_desc.accounting_description,
46+
)
47+
self.assertEqual(
48+
inv_line_with_product.product_id.name, inv_line_with_product.external_name
49+
)
50+
51+
def test_invoice_line_without_accounting_description(self):
52+
invoice_form_no_acc_desc = Form(
53+
self.account_move.with_context(default_move_type="out_invoice")
54+
)
55+
56+
invoice_form_no_acc_desc.partner_id = self.partner_1
57+
58+
with invoice_form_no_acc_desc.invoice_line_ids.new() as line_form:
59+
line_form.product_id = self.product_without_acc_desc
60+
line_form.quantity = 1
61+
line_form.price_unit = 2.99
62+
63+
self.invoice_no_acc_desc = invoice_form_no_acc_desc.save()
64+
inv_line_with_product = self.invoice_no_acc_desc.invoice_line_ids.filtered(
65+
lambda x: x.product_id
66+
)
67+
self.assertFalse(self.product_without_acc_desc.accounting_description)
68+
self.assertNotEqual(
69+
inv_line_with_product.name,
70+
self.product_without_acc_desc.accounting_description,
71+
)
72+
self.assertEqual(inv_line_with_product.name, self.product_without_acc_desc.name)
73+
self.assertEqual(
74+
inv_line_with_product.product_id.name, inv_line_with_product.external_name
75+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo>
3+
<record id="view_move_form" model="ir.ui.view">
4+
<field name="name">account_view_move_form</field>
5+
<field name="model">account.move</field>
6+
<field name="inherit_id" ref="account.view_move_form" />
7+
<field name="arch" type="xml">
8+
<xpath expr="//field[@name='invoice_line_ids']//tree" position="inside">
9+
<field name="external_name" />
10+
</xpath>
11+
<xpath
12+
expr="//field[@name='invoice_line_ids']//tree//field[@name='name']"
13+
position="attributes"
14+
>
15+
<attribute name="invisible">1</attribute>
16+
</xpath>
17+
<xpath expr="//field[@name='invoice_line_ids']//form" position="inside">
18+
<field name="external_name" />
19+
</xpath>
20+
<!--
21+
WARNING: We need to display the field as invisible here although it
22+
is already defined on invoice_line_ids tree above. Having it
23+
defined only there would only set the external_name key with its
24+
value inside the invoice_line_ids key of the values dictionary
25+
that is passed to create function. However, this invoice_line_ids
26+
key is popped in account.move._move_autocomplete_invoice_lines_create
27+
function to keep only the line_ids to create the account.move and
28+
avoid duplicated account.move.line records. -->
29+
<xpath expr="//field[@name='line_ids']//tree" position="inside">
30+
<field name="external_name" invisible="1" />
31+
</xpath>
32+
</field>
33+
</record>
34+
</odoo>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo>
3+
<record id="product_template_form_view" model="ir.ui.view">
4+
<field name="name">product_template_form</field>
5+
<field name="model">product.template</field>
6+
<field name="inherit_id" ref="product.product_template_form_view" />
7+
<field name="arch" type="xml">
8+
<xpath expr="//page/group[@name='properties']" position="inside">
9+
<group string="Accounting">
10+
<field name="accounting_description" />
11+
</group>
12+
</xpath>
13+
</field>
14+
</record>
15+
</odoo>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
{
5+
"name": "Acccount Move Accounting Purchase Description",
6+
"version": "14.0.1.0.0",
7+
"summary": "Consider accounting description when invoicing purchase order",
8+
"author": "Camptocamp, Odoo Community Association (OCA)",
9+
"website": "https://github.com/OCA/account-invoicing",
10+
"license": "AGPL-3",
11+
"category": "Accounting & Finance",
12+
"depends": ["purchase", "product", "account_move_line_accounting_description"],
13+
"auto_install": True,
14+
"installable": True,
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import purchase_order
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo import models
5+
6+
7+
class PurchaseOrderLine(models.Model):
8+
_inherit = "purchase.order.line"
9+
10+
def _prepare_account_move_line(self, move=False):
11+
res = super()._prepare_account_move_line(move)
12+
res["external_name"] = res["name"]
13+
product_id = res.get("product_id")
14+
if product_id:
15+
product = self.env["product.product"].browse(product_id)
16+
if product.accounting_description:
17+
res["name"] = product.accounting_description
18+
return res
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Anna Janiszewska <[email protected]>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This module adds possibility to use product accounting description on purchase order.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import test_purchase_order_description
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copyright 2021 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
3+
4+
from odoo import fields
5+
from odoo.tests.common import SavepointCase
6+
7+
8+
class TestPurchaseOrderDescription(SavepointCase):
9+
@classmethod
10+
def setUpClass(cls):
11+
super().setUpClass()
12+
cls.partner_1 = cls.env.ref("base.res_partner_1")
13+
cls.product_with_acc_desc = cls.env.ref("product.product_product_1")
14+
cls.product_without_acc_desc = cls.env.ref("product.product_product_2")
15+
16+
consumable_cat = cls.env["product.category"].search(
17+
[("name", "=", "Consumable")]
18+
)
19+
20+
cls.product_with_acc_desc.categ_id = consumable_cat
21+
cls.product_without_acc_desc.categ_id = consumable_cat
22+
23+
cls.product_with_acc_desc.purchase_method = "purchase"
24+
cls.product_without_acc_desc.purchase_method = "purchase"
25+
26+
cls.product_with_acc_desc.accounting_description = "Product1_acc_desc"
27+
28+
cls.po_product_with_acc = cls.env["purchase.order"].create(
29+
{
30+
"partner_id": cls.partner_1.id,
31+
"order_line": [
32+
(
33+
0,
34+
0,
35+
{
36+
"product_id": cls.product_with_acc_desc.id,
37+
"product_qty": 5.0,
38+
"product_uom": cls.product_with_acc_desc.uom_id.id,
39+
"price_unit": 10,
40+
"date_planned": fields.Datetime.now(),
41+
},
42+
)
43+
],
44+
}
45+
)
46+
cls.po_product_with_acc_line = cls.po_product_with_acc.order_line
47+
cls.po_product_with_acc.button_confirm()
48+
cls.po_product_with_acc.button_approve()
49+
50+
cls.po_product_without_acc = cls.env["purchase.order"].create(
51+
{
52+
"partner_id": cls.partner_1.id,
53+
"order_line": [
54+
(
55+
0,
56+
0,
57+
{
58+
"product_id": cls.product_without_acc_desc.id,
59+
"product_qty": 5.0,
60+
"product_uom": cls.product_without_acc_desc.uom_id.id,
61+
"price_unit": 10,
62+
"date_planned": fields.Datetime.now(),
63+
},
64+
)
65+
],
66+
}
67+
)
68+
cls.po_product_without_acc_line = cls.po_product_without_acc.order_line
69+
cls.po_product_without_acc.button_confirm()
70+
cls.po_product_without_acc.button_approve()
71+
72+
def test_purchase_order_line_name(self):
73+
74+
# For 1st PO check invoice line is same as product description
75+
action_1 = self.po_product_with_acc.action_create_invoice()
76+
inv_1 = self.env["account.move"].browse(action_1["res_id"])
77+
inv_line_with_product = inv_1.line_ids.filtered(lambda x: x.product_id)
78+
79+
self.assertTrue(self.product_with_acc_desc.accounting_description)
80+
self.assertEqual(
81+
inv_line_with_product.name,
82+
self.product_with_acc_desc.accounting_description,
83+
)
84+
self.assertIn(
85+
inv_line_with_product.product_id.name, inv_line_with_product.external_name
86+
)
87+
88+
# For 2nd PO make sure invoice line name isn't set to product description
89+
action_2 = self.po_product_without_acc.action_create_invoice()
90+
inv_2 = self.env["account.move"].browse(action_2["res_id"])
91+
inv_line_with_product = inv_2.line_ids.filtered(lambda x: x.product_id)
92+
93+
self.assertFalse(self.product_without_acc_desc.accounting_description)
94+
self.assertNotEqual(
95+
inv_line_with_product.name,
96+
self.product_without_acc_desc.accounting_description,
97+
)
98+
self.assertIn(
99+
inv_line_with_product.product_id.name, inv_line_with_product.external_name
100+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import models
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
{
5+
"name": "Acccount Move Accounting Sale Order Description",
6+
"version": "14.0.1.0.0",
7+
"summary": "Consider accounting description when invoicing sale order",
8+
"author": "Camptocamp, Odoo Community Association (OCA)",
9+
"website": "https://github.com/OCA/account-invoicing",
10+
"license": "AGPL-3",
11+
"category": "Accounting & Finance",
12+
"depends": ["sale", "product", "account_move_line_accounting_description"],
13+
"auto_install": True,
14+
"installable": True,
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2021 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from . import sale_order

0 commit comments

Comments
 (0)