Contract Forecast

contract_forecast
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/18.0/contract_forecast
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
COMMITTERSsbejaoui, Weblate, OCA-git-bot, oca-ci, hda
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:30:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract_line_successor
    - contract
OCA/queue:
    - queue_job
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
    - base_sparse_field
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES requests
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
The contract_forecast module enhances the **Contract** module by
generating and managing **forecast periods** for each contract line. It
automatically calculates future invoicing amounts and dates, allowing
companies to better anticipate and report on expected revenues.

Forecasts are visible directly from the contract in a **pivot view** or
**list view**.

\## Features

- Generate forecast periods based on the contract's invoicing rules.
- View forecasts grouped by invoice date.
- Automatic regeneration of forecast periods when contract data changes
  (product, quantity, price, dates, etc.).
- Company-wide configuration to enable or disable forecasts.
- Configurable forecast interval and period type (monthly or yearly).
- Forecast period data includes:
  - Start and end dates
  - Expected invoice date
  - Quantity, unit price, discount, and subtotal (untaxed)
- Clean handling of auto-renewing and manually-ended contracts.

Code Analysis

Views touched (6)
XML IDNameModelTypeStatus
contract_contract_form_view contract.contract xpath Inherits contract.contract_contract_form_view
contract_line_forecast_period_graph_view contract.line.forecast.period.graph (in contract_forecast) contract.line.forecast.period graph New
contract_line_forecast_period_pivot_view contract.line.forecast.period.pivot (in contract_forecast) contract.line.forecast.period pivot New
contract_line_forecast_period_search_view contract.line.forecast.period search New
contract_line_forecast_period_tree_view contract.line.forecast.period list New
res_config_settings_form_view res.config.settings xpath Inherits contract.res_config_settings_form_view
Models touched (5)

New fields (0)

No new fields.

Public methods (2)
  • action_show_contract_forecast(self)
  • write(self, values)

New fields (1)
  • forecast_period_ids One2many → contract.line.forecast.period
    comodel_name='contract.line.forecast.period' inverse_name='contract_line_id' required=False string='Forecast Periods'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, values)

New fields (14)
  • company_id Many2one → res.company
    comodel_name='res.company' string='Company'
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' index=True ondelete='cascade' readonly=True related='contract_line_id.contract_id' required=True store=True
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' index=True ondelete='cascade' readonly=True required=True
  • currency_id Many2one
    related='contract_id.currency_id' store=True
  • date_end Date
    readonly=True required=True
  • date_invoice Date
    readonly=True required=True string='Invoice Date'
  • date_start Date
    readonly=True required=True
  • discount Float
    digits='Discount' help='Discount that is applied in generated invoices. It should be less or equal to 100' string='Discount (%)'
  • name Char
    readonly=True required=True
  • price_subtotal Monetary
    compute='_compute_price_subtotal' store=True string='Amount Untaxed'
  • price_unit Monetary
    string='Unit Price'
  • product_id Many2one → product.product
    comodel_name='product.product' index=True readonly=True related='contract_line_id.product_id' required=True store=True
  • quantity Float
    default=1.0 required=True
  • sequence Integer
    related='contract_line_id.sequence' store=True
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    default=12 string='Number of contract forecast Periods'
  • contract_forecast_rule_type Selection
    default='monthly' args: [('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • enable_contract_forecast Boolean
    default=True string='Enable contract forecast'
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    readonly=False related='company_id.contract_forecast_interval'
  • contract_forecast_rule_type Selection
    readonly=False related='company_id.contract_forecast_rule_type'
  • enable_contract_forecast Boolean
    readonly=False related='company_id.enable_contract_forecast'
Public methods (0)

No public methods.

REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/16.0/contract_forecast
VERSION
VERSION 1.1.0
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
COMMITTERSWeblate, OCA-git-bot, oca-ci, Florent Cayré, Lena MONTENOT / Honeyxilia
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:43
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
OCA/queue:
    - queue_job
odoo/odoo:
    - base
    - account
    - base_setup
    - web
    - product
    - mail
    - bus
    - web_tour
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - base_sparse_field
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
requests
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (6)
XML IDNameModelTypeStatus
contract_contract_form_view contract.contract.form (in contract_forcast) contract.contract xpath Inherits contract.contract_contract_form_view
contract_line_forecast_period_graph_view contract.line.forecast.period.graph (in contract_forecast) contract.line.forecast.period graph New
contract_line_forecast_period_pivot_view contract.line.forecast.period.pivot (in contract_forecast) contract.line.forecast.period pivot New
contract_line_forecast_period_search_view contract.line.forecast.period.search (in contract_forecast) contract.line.forecast.period search New
contract_line_forecast_period_tree_view contract.line.forecast.period.tree (in contract_forecast) contract.line.forecast.period tree New
res_config_settings_form_view res.config.settings xpath Inherits contract.res_config_settings_form_view
Models touched (5)

New fields (0)

No new fields.

Public methods (2)
  • action_show_contract_forecast(self)
  • write(self, values)

New fields (1)
  • forecast_period_ids One2many → contract.line.forecast.period
    comodel_name='contract.line.forecast.period' inverse_name='contract_line_id' required=False string='Forecast Periods'
Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, values)

New fields (13)
  • company_id Many2one → res.company
    comodel_name='res.company' string='Company'
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' index=True ondelete='cascade' readonly=True related='contract_line_id.contract_id' required=True store=True string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' index=True ondelete='cascade' readonly=True required=True string='Contract Line'
  • date_end Date
    readonly=True required=True
  • date_invoice Date
    readonly=True required=True string='Invoice Date'
  • date_start Date
    readonly=True required=True
  • discount Float
    digits='Discount' help='Discount that is applied in generated invoices. It should be less or equal to 100' string='Discount (%)'
  • name Char
    readonly=True required=True
  • price_subtotal Float
    compute='_compute_price_subtotal' digits='Account' store=True string='Amount Untaxed'
  • price_unit Float
    string='Unit Price'
  • product_id Many2one → product.product
    comodel_name='product.product' index=True readonly=True related='contract_line_id.product_id' required=True store=True string='Product'
  • quantity Float
    default=1.0 required=True
  • sequence Integer
    related='contract_line_id.sequence' store=True string='Sequence'
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    default=12 string='Number of contract forecast Periods'
  • contract_forecast_rule_type Selection
    default='monthly' args: [('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • enable_contract_forecast Boolean
    default=True string='Enable contract forecast'
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    readonly=False related='company_id.contract_forecast_interval' string='Number of contract forecast Periods'
  • contract_forecast_rule_type Selection
    readonly=False related='company_id.contract_forecast_rule_type'
  • enable_contract_forecast Boolean
    readonly=False related='company_id.enable_contract_forecast' string='Enable contract forecast'
Public methods (0)

No public methods.

REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/12.0/contract_forecast
VERSION
VERSION 1.2.0
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
COMMITTERSsbejaoui, Luis Felipe Mileo, OCA Transbot, oca-travis, OCA-git-bot
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:29:15
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
OCA/queue:
    - queue_job
odoo/odoo:
    - base
    - account
    - base_setup
    - web
    - product
    - decimal_precision
    - mail
    - bus
    - web_tour
    - uom
    - analytic
    - portal
    - http_routing
    - digest
    - auth_signup
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
requests
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (6)
XML IDNameModelTypeStatus
contract_contract_form_view contract.contract.form (in contract_forcast) contract.contract xpath Inherits contract.contract_contract_form_view
contract_line_forecast_period_graph_view contract.line.forecast.period.graph (in contract_forecast) contract.line.forecast.period graph New
contract_line_forecast_period_pivot_view contract.line.forecast.period.pivot (in contract_forecast) contract.line.forecast.period pivot New
contract_line_forecast_period_search_view contract.line.forecast.period.search (in contract_forecast) contract.line.forecast.period search New
contract_line_forecast_period_tree_view contract.line.forecast.period.tree (in contract_forecast) contract.line.forecast.period tree New
res_config_settings_form_view res.config.settings xpath Inherits contract.res_config_settings_form_view
Models touched (5)

New fields (0)

No new fields.

Public methods (2)
  • action_show_contract_forecast(self)
    @api.multi
  • write(self, values)
    @api.multi

New fields (1)
  • forecast_period_ids One2many → contract.line.forecast.period
    comodel_name='contract.line.forecast.period' inverse_name='contract_line_id' required=False string='Forecast Periods'
Public methods (2)
  • create(self, values)
    @api.model
  • write(self, values)
    @api.multi

New fields (13)
  • company_id Many2one → res.company
    comodel_name='res.company' string='Company'
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' index=True ondelete='cascade' readonly=True related='contract_line_id.contract_id' required=True store=True string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' index=True ondelete='cascade' readonly=True required=True string='Contract Line'
  • date_end Date
    readonly=True required=True string='Date End'
  • date_invoice Date
    readonly=True required=True string='Invoice Date'
  • date_start Date
    readonly=True required=True string='Date Start'
  • discount Float
    digits=dp.get_precision('Discount') help='Discount that is applied in generated invoices. It should be less or equal to 100' string='Discount (%)'
  • name Char
    readonly=True required=True string='Name'
  • price_subtotal Float
    compute='_compute_price_subtotal' digits=dp.get_precision('Account') store=True string='Amount Untaxed'
  • price_unit Float
    string='Unit Price'
  • product_id Many2one → product.product
    comodel_name='product.product' index=True readonly=True related='contract_line_id.product_id' required=True store=True string='Product'
  • quantity Float
    default=1.0 required=True
  • sequence Integer
    related='contract_line_id.sequence' store=True string='Sequence'
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    default=12 string='Number of contract forecast Periods'
  • contract_forecast_rule_type Selection
    default='monthly' args: [('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • enable_contract_forecast Boolean
    default=True string='Enable contract forecast'
Public methods (0)

No public methods.

New fields (3)
  • contract_forecast_interval Integer
    default=12 readonly=False related='company_id.contract_forecast_interval' string='Number of contract forecast Periods'
  • contract_forecast_rule_type Selection
    default='monthly' readonly=False related='company_id.contract_forecast_rule_type' args: [('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • enable_contract_forecast Boolean
    default=True readonly=False related='company_id.enable_contract_forecast' string='Enable contract forecast'
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_forecast (#1464)