Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD module contract_fixed_discount #1009

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions contract/models/abstract_contract_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,18 @@ def _inverse_price_unit(self):
for line in self.filtered(lambda x: not x.automatic_price):
line.specific_price = line.price_unit

def _compute_price_subtotal_helper(self):
self.ensure_one()
subtotal = self.quantity * self.price_unit
discount = self.discount / 100
subtotal *= 1 - discount
return subtotal

@api.depends("quantity", "price_unit", "discount")
def _compute_price_subtotal(self):
for line in self:
subtotal = line.quantity * line.price_unit
discount = line.discount / 100
subtotal *= 1 - discount
subtotal = line._compute_price_subtotal_helper()

if line.contract_id.pricelist_id:
cur = line.contract_id.pricelist_id.currency_id
line.price_subtotal = cur.round(subtotal)
Expand Down
Empty file.
1 change: 1 addition & 0 deletions contract_fixed_discount/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
21 changes: 21 additions & 0 deletions contract_fixed_discount/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
"name": "Contract Fixed Discount",
"version": "14.0.1.0.0",
"category": "Contract Management",
"author": "Foodles, Odoo Community Association (OCA)",
"maintainers": [],
"website": "https://github.com/OCA/contract",
"depends": [
"account_invoice_fixed_discount",
"contract",
],
"data": [
"views/abstract_contract_line.xml",
"views/contract_line.xml",
"views/contract.xml",
],
"license": "AGPL-3",
"installable": True,
}
1 change: 1 addition & 0 deletions contract_fixed_discount/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import abstract_contract_line, contract_line
47 changes: 47 additions & 0 deletions contract_fixed_discount/models/abstract_contract_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class ContractAbstractContractLine(models.AbstractModel):
_inherit = "contract.abstract.contract.line"

discount_fixed = fields.Float(
string="Discount (Fixed)",
digits="Product Price",
default=0.00,
help="Fixed amount discount.",
)

@api.onchange("discount")
def _onchange_discount(self):
if self.discount:
self.discount_fixed = 0.0

@api.onchange("discount_fixed")
def _onchange_discount_fixed(self):
if self.discount_fixed:
self.discount = 0.0

@api.constrains("discount", "discount_fixed")
def _check_only_one_discount(self):
for rec in self:
for line in rec:
if line.discount and line.discount_fixed:
raise ValidationError(
_("You can only set one type of discount per line.")
)

def _compute_price_subtotal_helper(self):
self.ensure_one()
subtotal = self.quantity * self.price_unit
if self.discount:
subtotal = super()._compute_price_subtotal_helper()
elif self.discount_fixed:
subtotal -= self.discount_fixed
return subtotal

@api.depends("quantity", "price_unit", "discount", "discount_fixed")
def _compute_price_subtotal(self):
super()._compute_price_subtotal()
12 changes: 12 additions & 0 deletions contract_fixed_discount/models/contract_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import models


class ContractLine(models.Model):
_inherit = "contract.line"

def _prepare_invoice_line(self, move_form):
vals = super()._prepare_invoice_line(move_form=move_form)
vals["discount_fixed"] = self.discount_fixed
return vals
4 changes: 4 additions & 0 deletions contract_fixed_discount/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* `Foodles <https://www.foodles.co>`_:

* Damien Crier <damien.crier@foodles.co>
* Pierre Verkest <pierreverkest84@gmail.com>
1 change: 1 addition & 0 deletions contract_fixed_discount/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This module extends the functionality of contracts to allow you to apply fixed amount discounts at contract line level.
1 change: 1 addition & 0 deletions contract_fixed_discount/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_contract_discount_fixed, test_contract_invoice_discount_fixed
64 changes: 64 additions & 0 deletions contract_fixed_discount/tests/test_contract_discount_fixed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright 2023 Foodles (http://www.foodles.co/)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.exceptions import ValidationError
from odoo.tests import Form

from odoo.addons.contract.tests.test_contract import TestContractBase


class TestContractDiscounts(TestContractBase):
@classmethod
def setUpClass(cls):
super().setUpClass()

cls.contract4 = cls.env["contract.contract"].create(
{
"name": "Test Contract4",
"partner_id": cls.partner.id,
"pricelist_id": cls.partner.property_product_pricelist.id,
"line_recurrence": True,
"contract_line_ids": [
(
0,
0,
{
"product_id": cls.product_1.id,
"name": "Services from #START# to #END#",
"quantity": 1,
"uom_id": cls.product_1.uom_id.id,
"price_unit": 100,
"discount_fixed": 48,
"recurring_rule_type": "monthly",
"recurring_interval": 1,
"date_start": "2018-02-15",
"recurring_next_date": "2018-02-22",
},
)
],
}
)

def test_onchange_discount(self):
contract = Form(self.contract)
line = contract.contract_line_ids.edit(0)
line.discount_fixed = 42
self.assertFalse(line.discount)

def test_onchange_discount_fixed(self):
contract = Form(self.contract)
line = contract.contract_line_ids.edit(0)
line.discount = 42
self.assertFalse(line.discount_fixed)

def test_constraint_discount_discount_fixed(self):
with self.assertRaisesRegex(
ValidationError, "You can only set one type of discount per line."
):
self.contract4.contract_line_ids.discount = 42

def test_price_subtotal_discount_percent(self):
self.assertEqual(self.contract.contract_line_ids.price_subtotal, 50.0)

def test_price_subtotal_discount_fixed(self):
self.assertEqual(self.contract4.contract_line_ids.price_subtotal, 52.0)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2023 Foodles (http://www.foodles.co/)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.addons.contract.tests.test_contract import TestContractBase


class TestContractDiscounts(TestContractBase):
@classmethod
def setUpClass(cls):
super().setUpClass()

cls.contract4 = cls.env["contract.contract"].create(
{
"name": "Test Contract4",
"partner_id": cls.partner.id,
"pricelist_id": cls.partner.property_product_pricelist.id,
"line_recurrence": True,
"contract_line_ids": [
(
0,
0,
{
"product_id": cls.product_1.id,
"name": "Services from #START# to #END#",
"quantity": 1,
"uom_id": cls.product_1.uom_id.id,
"price_unit": 100,
"discount_fixed": 48,
"recurring_rule_type": "monthly",
"recurring_interval": 1,
"date_start": "2018-02-15",
"recurring_next_date": "2018-02-22",
},
)
],
}
)

def test_invoice_lines_discount_fixed(self):
invoice = self.contract4.recurring_create_invoice()
self.assertEquals(invoice.invoice_line_ids.discount_fixed, 48)
self.assertEquals(invoice.invoice_line_ids.discount, 0)
27 changes: 27 additions & 0 deletions contract_fixed_discount/views/abstract_contract_line.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record
id="contract_abstract_contract_line_add_discount_fixed_form_view"
model="ir.ui.view"
>
<field
name="name"
>contract.abstract.contract.line form view (in contract)</field>
<field name="model">contract.abstract.contract.line</field>
<field
name="inherit_id"
ref="contract.contract_abstract_contract_line_form_view"
/>

<field name="arch" type="xml">
<field name="discount" position="after">
<field
name="discount_fixed"
groups="product.group_discount_per_so_line"
/>
</field>
</field>
</record>

</odoo>
30 changes: 30 additions & 0 deletions contract_fixed_discount/views/contract.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="contract_contract_form_view" model="ir.ui.view">
<field name="name">contract.contract form view (in contract)</field>
<field name="model">contract.contract</field>
<field name="inherit_id" ref="contract.contract_contract_form_view" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='contract_line_fixed_ids']//tree//field[@name='discount']"
position="after"
>
<field
name="discount_fixed"
groups="product.group_discount_per_so_line"
optional="show"
/>
</xpath>
<xpath
expr="//field[@name='contract_line_ids']//tree//field[@name='discount']"
position="after"
>
<field
name="discount_fixed"
groups="product.group_discount_per_so_line"
optional="show"
/>
</xpath>
</field>
</record>
</odoo>
36 changes: 36 additions & 0 deletions contract_fixed_discount/views/contract_line.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="contract_line_tree_view" model="ir.ui.view">
<field name="name">contract.contract_line_tree_view</field>
<field name="model">contract.line</field>
<field name="inherit_id" ref="contract.contract_line_tree_view" />

<field name="arch" type="xml">
<field name="discount" position="after">
<field
name="discount_fixed"
groups="product.group_discount_per_so_line"
optional="show"
/>
</field>
</field>
</record>

<record id="contract_line_report_tree_view" model="ir.ui.view">
<field name="name">contract.contract_line_report_tree_view</field>
<field name="model">contract.line</field>
<field name="inherit_id" ref="contract.contract_line_report_tree_view" />

<field name="arch" type="xml">
<field name="discount" position="after">
<field
name="discount_fixed"
groups="product.group_discount_per_so_line"
optional="show"
/>
</field>
</field>
</record>

</odoo>
6 changes: 6 additions & 0 deletions setup/contract_fixed_discount/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)