Contract Line Successor

contract_line_successor
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/18.0/contract_line_successor
VERSION
VERSION 1.0.1
CATEGORY
CATEGORYUncategorized
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV
COMMITTERS
COMMITTERSDenis Roussel, Weblate, OCA-git-bot, oca-ci, Angel Rivas
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:30:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - base
    - account
    - base_setup
    - web
    - onboarding
    - product
    - mail
    - bus
    - web_tour
    - html_editor
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
**Contract Line Successor** extends `contract.line` model to support advanced
contract lifecycle management, including suspension, successor planning,
cancellation, and renewal.  
It provides a flexible and robust framework for managing complex contract
line scenarios in a clean and structured way.

## Features

- **Successor and Predecessor Management**
  - Link contract lines with successor and predecessor lines.
  - Plan successors automatically or manually after a stop or suspension.

- **Contract Line Lifecycle States**
  - Manage contract lines with the following computed states:
    - `Upcoming`
    - `In-Progress`
    - `To Renew`
    - `Upcoming Close`
    - `Closed`
    - `Canceled`

- **Lifecycle Operations**
  - Stop a contract line.
  - Plan a successor for a contract line.
  - Stop and plan a successor in one operation (useful for suspensions).
  - Cancel and un-cancel contract lines.
  - Renew contract lines automatically (new line or extension).

- **Auto-Renewal Handling**
  - Auto-renewal based on company settings (extend existing line or create a new one).
  - Cron job to automate renewal of eligible contract lines.

- **Data Integrity and Validation**
  - Prevent invalid successor or predecessor configurations.
  - Validate state transitions and date overlaps.
  - Ensure clean renewal and cancellation workflows.

- **Audit Trail**
  - Automatic posting of chatter messages for lifecycle events like stops, 
    renewals, suspensions, cancellations, etc.

Code Analysis

Views touched (12)
XML IDNameModelTypeStatus
contract_contract_form_view contract.contract xpath Inherits contract.contract_contract_form_view
contract_line_form_view contract.line header Inherits contract.contract_line_form_view
contract_line_report_tree_view contract.line xpath Inherits contract.contract_line_report_tree_view
contract_line_search_view contract.line xpath Inherits contract.contract_line_search_view
contract_line_tree_view contract.line xpath Inherits contract.contract_line_tree_view
contract_line_wizard_plan_successor_form_view contract.line.plan_successor.wizard.form (in contract) contract.line.wizard form New
contract_line_wizard_stop_form_view contract.line.stop.wizard.form (in contract) contract.line.wizard form New
contract_line_wizard_stop_plan_successor_form_view contract.line.stop_plan_successor.wizard.form (in contract) contract.line.wizard form New
contract_line_wizard_uncancel_form_view contract.line.stop_plan_successor.wizard.form (in contract) contract.line.wizard form New
contract_template_form_view contract.template xpath Inherits contract.contract_template_form_view
contract_template_line_form_view contract.template.line xpath Inherits contract.contract_template_line_form_view
res_config_settings_form_view res.config.settings xpath Inherits contract.res_config_settings_form_view
Models touched (7)

New fields (1)
  • line_recurrence Boolean
    default=True
Public methods (0)

No public methods.

New fields (10)
  • is_cancel_allowed Boolean
    compute='_compute_allowed' string='Cancel allowed?'
  • is_plan_successor_allowed Boolean
    compute='_compute_allowed' string='Plan successor allowed?'
  • is_stop_allowed Boolean
    compute='_compute_allowed' string='Stop allowed?'
  • is_stop_plan_successor_allowed Boolean
    compute='_compute_allowed' string='Stop/Plan successor allowed?'
  • is_un_cancel_allowed Boolean
    compute='_compute_allowed' string='Un-Cancel allowed?'
  • manual_renew_needed Boolean
    default=False help='This flag is used to make a difference between a definitive stopand temporary one for which a user is not able to plan asuccessor in advance'
  • predecessor_contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False help='Contract Line origin of this one.' index=True readonly=True required=False string='Predecessor Contract Line'
  • state Selection
    compute='_compute_state' search='_search_state' selection=[('upcoming', 'Upcoming'), ('in-progress', 'In-progress'), ('to-renew', 'To renew'), ('upcoming-close', 'Upcoming Close'), ('closed', 'Closed'), ('canceled', 'Canceled')]
  • successor_contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False help='In case of restart after suspension, this field contain the new contract line created.' index=True readonly=True required=False string='Successor Contract Line'
  • termination_notice_date Date
    compute='_compute_termination_notice_date' copy=False store=True
Public methods (12)
  • action_plan_successor(self)
  • action_stop(self)
  • action_stop_plan_successor(self)
  • action_uncancel(self)
  • cancel(self)
  • cron_renew_contract_line(self)
    @api.model
  • plan_successor(self, date_start, date_end, is_auto_renew, recurring_next_date=False, post_message=True)
    Create a copy of a contract line in a new interval :param date_start: date_start for the successor_contract_line :param date_end: date_end for the successor_contract_line :param is_auto_renew: is_auto_renew option for successor_contract_line :param recurring_next_date: recurring_next_date for the successor_contract_line :return: successor_contract_line
  • renew(self)
  • stop(self, date_end, manual_renew_needed=False, post_message=True)
    Put date_end on contract line We don't consider contract lines that end's before the new end date :param date_end: new date end for contract line :return: True
  • stop_plan_successor(self, date_start, date_end, is_auto_renew)
    Stop a contract line for a defined period and start it later Cases to consider: * contract line end's before the suspension period: -> apply stop * contract line start before the suspension period and end in it -> apply stop at suspension start date -> apply plan successor: - date_start: suspension.date_end - date_end: date_end + (contract_line.date_end - suspension.date_start) * contract line start before the suspension period and end after it -> apply stop at suspension start date -> apply plan successor: - date_start: suspension.date_end - date_end: date_end + (suspension.date_end - suspension.date_start) * contract line start and end's in the suspension period -> apply delay - delay: suspension.date_end - contract_line.date_start * contract line start in the suspension period and end after it -> apply delay - delay: suspension.date_end - contract_line.date_start * contract line start and end after the suspension period -> apply delay - delay: suspension.date_end - suspension.start_date :param date_start: suspension start date :param date_end: suspension end date :param is_auto_renew: is the new line is set to auto_renew :return: created contract line
  • uncancel(self, recurring_next_date)
  • unlink(self)
    stop unlink uncnacled lines

New fields (6)
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' index=True ondelete='cascade' required=True string='Contract Line'
  • date_end Date
  • date_start Date
  • is_auto_renew Boolean
    default=False
  • manual_renew_needed Boolean
    default=False help='This flag is used to make a difference between a definitive stopand temporary one for which a user is not able to plan asuccessor in advance'
  • recurring_next_date Date
    string='Next Invoice Date'
Public methods (4)
  • plan_successor(self)
  • stop(self)
  • stop_plan_successor(self)
  • uncancel(self)

New fields (1)
  • is_auto_renew Boolean
    compute='_compute_is_auto_renew'
Public methods (0)

No public methods.

New fields (5)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Weeks/Months/Years)' string='Renew Every'
  • auto_renew_rule_type Selection
    default='yearly' help='Specify interval for automatic renewal.' string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • termination_notice_interval Integer
    default=1 string='Termination Notice Before'
  • termination_notice_rule_type Selection
    default='monthly' string='Termination Notice type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)')]
Public methods (0)

No public methods.

New fields (1)
  • create_new_line_at_contract_line_renew Boolean
    help='If checked, a new line will be generated at contract line renew and linked to the original one as successor. The default behavior is to extend the end date of the contract by a new subscription period'
Public methods (0)

No public methods.

New fields (1)
  • create_new_line_at_contract_line_renew Boolean
    help='If checked, a new line will be generated at contract line renew and linked to the original one as successor. The default behavior is to extend the end date of the contract by a new subscription period' readonly=False related='company_id.create_new_line_at_contract_line_renew' string='Create New Line At Contract Line Renew'
Public methods (0)

No public methods.

STATUS
STATUSOpen migration PR - not merged yet for this version
REPOSITORY
REPOSITORYOCA/contract
PULL REQUEST
PULL REQUEST[19.0][MIG] contract_line_successor (#1370)
STATUS
STATUSOpen migration PR - not merged yet for this version
REPOSITORY
REPOSITORYOCA/contract
PULL REQUEST
PULL REQUEST19.0 [MIG] contract line successor (#1334)