Skip to content
Open
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
10 changes: 1 addition & 9 deletions contract/models/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,14 +568,6 @@ def _get_lines_to_invoice(self, date_ref):
"""
self.ensure_one()

def can_be_invoiced(contract_line):
return (
not contract_line.is_canceled
and contract_line.recurring_next_date
and contract_line.recurring_next_date <= date_ref
and contract_line.next_period_date_start
)

lines2invoice = previous = self.env["contract.line"]
current_section = current_note = False
for line in self.contract_line_ids:
Expand All @@ -589,7 +581,7 @@ def can_be_invoiced(contract_line):
elif line.note_invoicing_mode == "with_next_line":
current_note = line
elif line.is_recurring_note or not line.display_type:
if can_be_invoiced(line):
if line._can_be_invoiced(date_ref):
if current_section:
lines2invoice |= current_section
current_section = False
Expand Down
9 changes: 9 additions & 0 deletions contract/models/contract_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ def _update_last_date_invoiced(self):
}
)

def _can_be_invoiced(self, date_ref):
self.ensure_one()
return (
not self.is_canceled
and self.recurring_next_date
and self.recurring_next_date <= date_ref
and self.next_period_date_start
)

@api.model
def get_view(self, view_id=None, view_type="form", **options):
default_contract_type = self.env.context.get("default_contract_type")
Expand Down
148 changes: 148 additions & 0 deletions contract_line_defer/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
===================
Contract Line Defer
===================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:5026e9d29520acf8591e453f1a7b5d8b1c3fab840a5735bcad4a77e8e07bc944
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/licence-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%2Fcontract-lightgray.png?logo=github
:target: https://github.com/OCA/contract/tree/18.0/contract_line_defer
:alt: OCA/contract
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/contract-18-0/contract-18-0-contract_line_defer
: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/contract&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

Enable to defer contract line's invoicing. If a contract line start date
is not known, it can be deferred. It will not be invoiced until manually
activated.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

BUSINESS NEED:

- Your company sells contracts which start dates are not known at the
conclusion of the sale.
- Lines which start dates are not confirmed should not be invoiced

APPROACH:

- This module adds a "deferred" flag on the contract line, that can be
enabled and disabled via a button
- A deferred line is not invoiced until manually activated
- A company setting allows deferring all contract lines by default

USEFUL INFORMATION:

- Use the module **contract_line_defer_product** when also using
contract products (module **product_contract**)

Configuration
=============

To configure this module, you need to:

1. Go to *Invoicing/Accounting* > Configuration > Settings > Contract
2. Select **Defer contract line start** if you want to defer contract
lines by default. Use this setting if you sell contracts which start
dates are unknown at the conclusion of the sale.

Usage
=====

Optional Settings
-----------------

1. Go to *Invoicing/Accounting* > Configuration > Settings > Contract
2. Select **Defer contract line start** if you want to defer contract
lines by default. Use this setting if you sell contracts which start
dates are unknown at the conclusion of the sale.

|Company Settings|

Add a contract line
-------------------

When adding a contract line, you can select **Deferred** instead of a
start date

|New Contract Line|

Modify a contract line
----------------------

An existing contract line can be deferred and activated via a button on
the line

|Edit Contract Line|

Activate a contract line
------------------------

When activating a line, a new start (and optionally end) date can be
chosen.

.. |Company Settings| image:: https://raw.githubusercontent.com/OCA/contract/18.0/contract_line_defer/static/src/company_settings.png
.. |New Contract Line| image:: https://raw.githubusercontent.com/OCA/contract/18.0/contract_line_defer/static/src/contract_line_new.png
.. |Edit Contract Line| image:: https://raw.githubusercontent.com/OCA/contract/18.0/contract_line_defer/static/src/contract_line_edit.png

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/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/contract/issues/new?body=module:%20contract_line_defer%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
-------

* ACSONE SA/NV

Contributors
------------

- Tobias Zehntner tobias.zehntner@acsone.eu (ACSONE SA/NV)

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.

This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/18.0/contract_line_defer>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions contract_line_defer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
21 changes: 21 additions & 0 deletions contract_line_defer/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Contract Line Defer",
"summary": """Defer Contract Lines to avoid invoicing while start date unknown""",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/contract",
"depends": [
"contract",
],
"data": [
"security/contract_line_activate_wizard.xml",
"wizards/contract_line_activate_wizard.xml",
"views/contract.xml",
"views/contract_line.xml",
"views/res_config_settings.xml",
],
}
4 changes: 4 additions & 0 deletions contract_line_defer/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import contract_line
from . import res_company
from . import res_config_settings
from . import contract_recurring_mixin
37 changes: 37 additions & 0 deletions contract_line_defer/models/contract_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, fields, models


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

def _check_recurring_next_date_recurring_invoices(self):
return super(
ContractLine, self.filtered(lambda line: not line.is_deferred)
)._check_recurring_next_date_recurring_invoices()

@api.depends("is_deferred")
def _compute_display_name(self):
res = super()._compute_display_name()
for rec in self:
if rec.is_deferred:
rec.display_name = f"Deferred - {rec.name}"
return res

@api.onchange("is_deferred")
def _onchange_is_deferred(self):
"""
If activating a contract line, make sure start/end dates are compatible
"""
self.ensure_one()
if not self.is_deferred:
today = fields.date.today()
if self.date_start < today:
self.date_start = today
if self.date_end and self.date_end < today:
self.date_end = False

def _can_be_invoiced(self, date_ref):
return not self.is_deferred and super()._can_be_invoiced(date_ref)
40 changes: 40 additions & 0 deletions contract_line_defer/models/contract_recurring_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, fields, models


class ContractRecurringMixin(models.AbstractModel):
_inherit = "contract.recurring.mixin"

is_deferred = fields.Boolean(
"Deferred", help="Do not invoice this line until it is activated"
)

@api.model
def default_get(self, fields):
result = super().default_get(fields)
if "is_deferred" in fields:
company = (
self.env["res.company"].browse(company_id)
if (company_id := result.get("company_id"))
else self.env.company
)
if company.defer_contract_line_start:
result["is_deferred"] = True
return result

def enable_deferred(self):
self.ensure_one()
self.is_deferred = True

@api.depends("is_deferred")
def _compute_recurring_next_date(self):
"""No next invoice date for deferred lines"""
res = super()._compute_recurring_next_date()
self.filtered(lambda r: r.is_deferred).update({"recurring_next_date": False})
return res

@api.depends("is_deferred")
def _compute_next_period_date_start(self):
return super()._compute_next_period_date_start()
15 changes: 15 additions & 0 deletions contract_line_defer/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

defer_contract_line_start = fields.Boolean(
"Defer contract line start",
help="At creation, defer contract lines by default (i.e. do not invoice until "
"activated). Use this setting if you sell contracts which start dates are "
"unknown at the conclusion of the sale.",
)
13 changes: 13 additions & 0 deletions contract_line_defer/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

defer_contract_line_start = fields.Boolean(
related="company_id.defer_contract_line_start",
readonly=False,
)
3 changes: 3 additions & 0 deletions contract_line_defer/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
5 changes: 5 additions & 0 deletions contract_line_defer/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
To configure this module, you need to:

1. Go to *Invoicing/Accounting* > Configuration > Settings > Contract
1. Select **Defer contract line start** if you want to defer contract lines by default. Use this setting if you sell contracts which start dates are unknown at the conclusion of the sale.

11 changes: 11 additions & 0 deletions contract_line_defer/readme/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
BUSINESS NEED:
- Your company sells contracts which start dates are not known at the conclusion of the sale.
- Lines which start dates are not confirmed should not be invoiced

APPROACH:
- This module adds a "deferred" flag on the contract line, that can be enabled and disabled via a button
- A deferred line is not invoiced until manually activated
- A company setting allows deferring all contract lines by default

USEFUL INFORMATION:
- Use the module **contract_line_defer_product** when also using contract products (module **product_contract**)
1 change: 1 addition & 0 deletions contract_line_defer/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Tobias Zehntner <tobias.zehntner@acsone.eu> (ACSONE SA/NV)
1 change: 1 addition & 0 deletions contract_line_defer/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enable to defer contract line's invoicing. If a contract line start date is not known, it can be deferred. It will not be invoiced until manually activated.
28 changes: 28 additions & 0 deletions contract_line_defer/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Optional Settings
-----------------

1. Go to *Invoicing/Accounting* > Configuration > Settings > Contract
1. Select **Defer contract line start** if you want to defer contract lines by default. Use this setting if you sell contracts which start dates are unknown at the conclusion of the sale.

![Company Settings](../static/src/company_settings.png)

Add a contract line
-------------------

When adding a contract line, you can select **Deferred** instead of a start date

![New Contract Line](../static/src/contract_line_new.png)

Modify a contract line
----------------------

An existing contract line can be deferred and activated via a button on the line

![Edit Contract Line](../static/src/contract_line_edit.png)

Activate a contract line
------------------------

When activating a line, a new start (and optionally end) date can be chosen.

14 changes: 14 additions & 0 deletions contract_line_defer/security/contract_line_activate_wizard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2025 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.model.access" id="access_contract_line_activate_wizard_user">
<field name="name">access_contract_line_activate_wizard_user</field>
<field name="model_id" ref="model_contract_line_activate_wizard" />
<field name="group_id" ref="account.group_account_invoice" />
<field name="perm_read" eval="1" />
<field name="perm_create" eval="1" />
<field name="perm_write" eval="1" />
<field name="perm_unlink" eval="1" />
</record>
</odoo>
Binary file added contract_line_defer/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading