Recurring - Product Contract

product_contract
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/18.0/product_contract
VERSION
VERSION 1.1.4
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSCarlos Lopez, sbejaoui, Víctor Martínez, Weblate, OCA-git-bot, oca-ci, Benoit Aimont, Tobias Zehntner, Angel Rivas, bo-eska, bjouini
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:30:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract_termination
    - contract_line_successor
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
    - uom
    - account
    - onboarding
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - account_payment
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
This module adds support for products to be linked to contract
templates.

A contract is created on `sale.order` confirmation for each different
template used in sale order line where recurrence details are set too.

Contract product are ignored on invoicing process and pass to nothing to
invoice directly.

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_contract_configurator_form product.contract.configurator form New
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (9)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (1)
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (16)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • contract_start_date_method Selection
    default='manual' help="This field allows to define how the start date of the contract will\n be calculated:\n\n - Manual: The start date will be selected by the user, by default will be the\n date of sale confirmation.\n - Start of current period: The start date will be the first day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/01/01.\n - End of current period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/12/31.\n - Start of next period: The start date will be the first day of the next\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/01/01.\n - End of next period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/12/31.\n " args: [('manual', 'Manual'), ('start_this', 'Start of current period'), ('end_this', 'End of current period'), ('start_next', 'Start of next period'), ('end_next', 'End of next period')], 'Start Date Method'
  • force_month_quarterly Selection
    help='Force the month to be used inside the quarter' args: [('1', 'First month'), ('2', 'Second month'), ('3', 'Third month')], 'Force Month (quarterly)'
  • force_month_semesterly Selection
    help='Force the month to be used inside the semester' args: [('1', 'First month'), ('2', 'Second month'), ('3', 'Third month'), ('4', 'Fourth month'), ('5', 'Fifth month'), ('6', 'Sixth month')], 'Force Month (semesterly)'
  • force_month_yearly Selection
    args: [('1', 'January'), ('2', 'February'), ('3', 'March'), ('4', 'April'), ('5', 'May'), ('6', 'June'), ('7', 'July'), ('8', 'August'), ('9', 'September'), ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Force Month'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurrence_interval Selection
    default='monthly' help='Define the length of each recurrence period (e.g., every 1 month, every 3 months).' args: [('monthly', 'Month(s)'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • recurrence_number Integer
    default=1 help='Total number of recurrence periods for the contract.' string='Number of Recurrences'
  • recurring_interval Integer
    default=1 help='Frequency at which invoices are generated (e.g., every 1 month, every 2 weeks).' string='Invoice Every'
  • recurring_invoicing_type Selection
    default='pre-paid' help='Define whether invoices are issued before (prepaid) or after (postpaid) the service period.' string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify the time unit for generating recurring invoices (days, weeks, months, etc.).' string='Invoicing Recurrence' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (3)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)

New fields (0)

No new fields.

Public methods (2)
  • create_contract_line(self, contract)
  • invoice_line_create(self, invoice_id, qty)

New fields (19)
  • auto_renew_interval Integer
    compute='_compute_product_contract_data' default=1 help='Renew every (Days/Week/Month/Year)' precompute=True readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_product_contract_data' default='yearly' help='Specify Interval for automatic renewal.' precompute=True readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • company_id Many2one → res.company
    args: 'res.company'
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' required=False string='Contract Line to replace'
  • contract_start_date_method Selection
    compute='_compute_product_contract_data' default='manual' help="This field allows to define how the start date of the contract will\n be calculated:\n\n - Manual: The start date will be selected by the user, by default will be the\n date of sale confirmation.\n - Start of current period: The start date will be the first day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/01/01.\n - End of current period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/12/31.\n - Start of next period: The start date will be the first day of the next\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/01/01.\n - End of next period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/12/31.\n " precompute=True readonly=False store=True args: [('manual', 'Manual'), ('start_this', 'Start of current period'), ('end_this', 'End of current period'), ('start_next', 'Start of next period'), ('end_next', 'End of next period')], 'Start Date Method'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    compute='_compute_contract_line_date_end' precompute=True readonly=False store=True
  • date_start Date
    compute='_compute_contract_line_date_start' precompute=True readonly=False store=True
  • is_auto_renew Boolean
    compute='_compute_product_contract_data' default=False precompute=True readonly=False store=True string='Auto Renew'
  • is_contract Boolean
    related='product_id.is_contract' string='Is a contract'
  • partner_id Many2one → res.partner
    args: 'res.partner'
  • product_id Many2one → product.product
    args: 'product.product'
  • product_uom_qty Float
    args: 'Quantity'
  • recurrence_interval Selection
    compute='_compute_product_contract_data' default='monthly' help='Specify Interval for contract duration.' precompute=True readonly=False store=True args: [('monthly', 'Month(s)'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • recurrence_number Integer
    compute='_compute_product_contract_data' precompute=True readonly=False store=True
  • recurring_interval Integer
    compute='_compute_product_contract_data' default=1 help='Invoice every (Days/Week/Month/Year)' precompute=True readonly=False store=True string='Invoice Every'
  • recurring_invoicing_type Selection
    compute='_compute_product_contract_data' default='pre-paid' help='Specify if the invoice must be generated at the beginning (pre-paid) or end (post-paid) of the period.' precompute=True readonly=False store=True string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    compute='_compute_product_contract_data' default='monthly' help='Specify Interval for automatic invoice generation.' precompute=True readonly=False store=True string='Recurrence' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
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/17.0/product_contract
VERSION
VERSION 2.3.0
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSCarlos Lopez, sergio-teruel, Weblate, OCA-git-bot, Abraham Anes, oca-ci, Carlos Roca, CarlosRoca13, David Jaen
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:20:04
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - account
    - onboarding
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - account_payment
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
This module adds support for products to be linked to contract
templates.

A contract is created on `sale.order` confirmation for each different
template used in sale order line where recurrence details are set too.

Contract product are ignored on invoicing process and pass to nothing to
invoice directly.

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_contract_configurator_form product.contract.configurator form New
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (8)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (1)
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (17)
  • auto_renew_interval Integer
    compute='_compute_auto_renew' default=1 help='Renew every (Days/Week/Month/Year)' readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_auto_renew' default='yearly' help='Specify Interval for automatic renewal.' readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • avoid_create_contract Boolean
  • company_id Many2one → res.company
    args: 'res.company'
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' required=False string='Contract Line to replace'
  • contract_start_date_method Selection
    related='product_id.contract_start_date_method'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    compute='_compute_date_end' readonly=False store=True
  • date_start Date
  • is_auto_renew Boolean
    compute='_compute_auto_renew' default=False readonly=False store=True string='Auto Renew'
  • partner_id Many2one → res.partner
    args: 'res.partner'
  • product_id Many2one → product.product
    args: 'product.product'
  • product_uom_qty Float
    args: 'Quantity'
  • recurring_interval Integer
    default=1 help='Invoice every (Days/Week/Month/Year)' string='Invoice Every'
  • recurring_invoicing_type Selection
    related='product_id.recurring_invoicing_type'
  • recurring_rule_type Selection
    related='product_id.recurring_rule_type'
Public methods (0)

No public methods.

New fields (14)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • contract_start_date_method Selection
    default='manual' help="This field allows to define how the start date of the contract will\n be calculated:\n\n - Manual: The start date will be selected by the user, by default will be the\n date of sale confirmation.\n - Start of current period: The start date will be the first day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/01/01.\n - End of current period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2024/12/31.\n - Start of next period: The start date will be the first day of the next\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/01/01.\n - End of next period: The start date will be the last day of the actual\n period selected on 'Invoicing Every' field. Example: If we are on 2024/08/27\n and the period selected is 'Year(s)' the start date will be 2025/12/31.\n " args: [('manual', 'Manual'), ('start_this', 'Start of current period'), ('end_this', 'End of current period'), ('start_next', 'Start of next period'), ('end_next', 'End of next period')], 'Start Date Method'
  • default_qty Integer
    default=1 string='Default Quantity'
  • force_month_quarterly Selection
    help='Force the month to be used inside the quarter' args: [('1', 'First month'), ('2', 'Second month'), ('3', 'Third month')], 'Force Month'
  • force_month_semesterly Selection
    help='Force the month to be used inside the semester' args: [('1', 'First month'), ('2', 'Second month'), ('3', 'Third month'), ('4', 'Fourth month'), ('5', 'Fifth month'), ('6', 'Sixth month')], 'Force Month'
  • force_month_yearly Selection
    args: [('1', 'January'), ('2', 'February'), ('3', 'March'), ('4', 'April'), ('5', 'May'), ('6', 'June'), ('7', 'July'), ('8', 'August'), ('9', 'September'), ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Force Month'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (3)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)

New fields (15)
  • auto_renew_interval Integer
    compute='_compute_auto_renew' default=1 help='Renew every (Days/Week/Month/Year)' precompute=True readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_auto_renew' default='yearly' help='Specify Interval for automatic renewal.' precompute=True readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • avoid_create_contract Boolean
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False string='Contract Line to replace'
  • contract_start_date_method Selection
    related='product_id.contract_start_date_method'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    compute='_compute_date_end' precompute=True readonly=False store=True
  • date_start Date
    compute='_compute_date_start' precompute=True readonly=False store=True
  • is_auto_renew Boolean
    compute='_compute_auto_renew' precompute=True readonly=False store=True string='Auto Renew'
  • is_contract Boolean
    related='product_id.is_contract' string='Is a contract'
  • product_contract_description Text
    compute='_compute_product_contract_description'
  • recurring_interval Integer
    default=1 help='Invoice every (Days/Week/Month/Year)' string='Invoice Every'
  • recurring_invoicing_type Selection
    related='product_id.recurring_invoicing_type'
  • recurring_rule_type Selection
    related='product_id.recurring_rule_type'
Public methods (3)
  • create_contract_line(self, contract)
  • get_relative_delta(self, recurring_rule_type, interval)
    @api.model
  • invoice_line_create(self, invoice_id, qty)
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/16.0/product_contract
VERSION
VERSION 1.0.2
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSEnric Tobella, Weblate, OCA-git-bot, oca-ci, Simon Maillard, Rad0van
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:43
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - account
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - account_payment
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (4)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (7)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (1)
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (10)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • default_qty Integer
    default=1 string='Default Quantity'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (3)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)

New fields (11)
  • auto_renew_interval Integer
    compute='_compute_auto_renew' default=1 help='Renew every (Days/Week/Month/Year)' readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_auto_renew' default='yearly' help='Specify Interval for automatic renewal.' readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False required=False string='Contract Line to replace'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
  • date_start Date
  • is_auto_renew Boolean
    compute='_compute_auto_renew' default=False readonly=False store=True string='Auto Renew'
  • is_contract Boolean
    related='product_id.is_contract' string='Is a contract'
  • recurring_invoicing_type Selection
    copy=False default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    copy=False default='monthly' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
Public methods (3)
  • create_contract_line(self, contract)
  • invoice_line_create(self, invoice_id, qty)
  • onchange_date_start(self)
    @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type')
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/15.0/product_contract
VERSION
VERSION 1.1.1
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSVíctor Martínez, Weblate, OCA-git-bot, oca-ci, Adasat
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:46:32
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - account
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (4)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (7)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (1)
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (10)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • default_qty Integer
    default=1 string='Default Quantity'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (3)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)

New fields (11)
  • auto_renew_interval Integer
    compute='_compute_auto_renew' default=1 help='Renew every (Days/Week/Month/Year)' readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_auto_renew' default='yearly' help='Specify Interval for automatic renewal.' readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False required=False string='Contract Line to replace'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
  • date_start Date
  • is_auto_renew Boolean
    compute='_compute_auto_renew' default=False readonly=False store=True string='Auto Renew'
  • is_contract Boolean
    string='Is a contract'
  • recurring_invoicing_type Selection
    copy=False default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    copy=False default='monthly' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
Public methods (4)
  • create_contract_line(self, contract)
  • invoice_line_create(self, invoice_id, qty)
  • onchange_date_start(self)
    @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type', 'is_contract')
  • product_id_change(self)
    @api.onchange('product_id')
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/14.0/product_contract
VERSION
VERSION 1.2.0
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSWeblate, OCA-git-bot, Mourad, oca-ci, Marcel Savegnago, Ilyas
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:40:55
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - account
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (4)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (7)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (1)
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (10)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • default_qty Integer
    default=1 string='Default Quantity'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (3)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)

New fields (11)
  • auto_renew_interval Integer
    compute='_compute_auto_renew' default=1 help='Renew every (Days/Week/Month/Year)' readonly=False store=True string='Renew Every'
  • auto_renew_rule_type Selection
    compute='_compute_auto_renew' default='yearly' help='Specify Interval for automatic renewal.' readonly=False store=True string='Renewal type' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')]
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False required=False string='Contract Line to replace'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    string='Date End'
  • date_start Date
    string='Date Start'
  • is_auto_renew Boolean
    compute='_compute_auto_renew' default=False readonly=False store=True string='Auto Renew'
  • is_contract Boolean
    string='Is a contract'
  • recurring_invoicing_type Selection
    copy=False default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    copy=False default='monthly' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
Public methods (4)
  • create_contract_line(self, contract)
  • invoice_line_create(self, invoice_id, qty)
  • onchange_date_start(self)
    @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type', 'is_contract')
  • product_id_change(self)
    @api.onchange('product_id')
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/13.0/product_contract
VERSION
VERSION 1.0.1
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSDenis Roussel, Weblate, OCA-git-bot, oca-ci
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:34:11
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - account
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - sale
    - sales_team
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (4)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (7)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)

New fields (2)
  • display_name Char
    compute='_compute_display_name_2'
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (10)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • default_qty Integer
    default=1 string='Default Quantity'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (4)
  • action_confirm(self)
    If we have a contract in the order, set it up
  • action_create_contract(self)
  • action_show_contracts(self)
  • check_contact_is_not_terminated(self)
    @api.constrains('state')

New fields (11)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False required=False string='Contract Line to replace'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    string='Date End'
  • date_start Date
    string='Date Start'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    related='product_id.is_contract' string='Is a contract'
  • recurring_invoicing_type Selection
    copy=False default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    copy=False default='monthly' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
Public methods (5)
  • check_contact_is_not_terminated(self)
    @api.constrains('contract_id')
  • create_contract_line(self, contract)
  • invoice_line_create(self, invoice_id, qty)
  • onchange_date_start(self)
    @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type')
  • onchange_product(self)
    @api.onchange('product_id')
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/12.0/product_contract
VERSION
VERSION 5.3.1
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), ACSONE SA/NV, LasLabs
COMMITTERS
COMMITTERSPedro M. Baeza, GitHub, Denis Roussel, Stéphane Bidoul (ACSONE), sbejaoui, nans, OCA Transbot, Thomas Binsfeld, oca-travis, Weblate, OCA-git-bot, sergiocorato, Marcel Savegnago, Oscar Soto, Kay Häusler
WEBSITE
WEBSITEhttps://github.com/OCA/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:29:15
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract_sale
    - contract
odoo/odoo:
    - product
    - base
    - decimal_precision
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - sale
    - sales_team
    - payment
    - account
    - analytic
    - portal
    - http_routing
    - digest
    - auth_signup
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES python-dateutil
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (4)
XML IDNameModelTypeStatus
contract_contract_customer_form_view contract.contract xpath Inherits contract.contract_contract_customer_form_view
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
res_config_settings_form_view res.config.settings.form (in product_contract) res.config.settings xpath Inherits sale.res_config_settings_view_form
view_order_form sale.order.form (in product_contract) sale.order xpath Inherits sale.view_order_form
Models touched (7)

New fields (1)
  • sale_order_count Integer
    compute='_compute_sale_order_count'
Public methods (1)
  • action_view_sales_orders(self)
    @api.multi

New fields (2)
  • display_name Char
    compute='_compute_display_name_2'
  • sale_order_line_id Many2one → sale.order.line
    comodel_name='sale.order.line' copy=False required=False string='Sale Order Line'
Public methods (0)

No public methods.

New fields (10)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • default_qty Integer
    default=1 string='Default Quantity'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    args: 'Is a contract'
  • property_contract_template_id Many2one → contract.template
    comodel_name='contract.template' company_dependent=True string='Contract Template'
  • recurring_invoicing_type Selection
    default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    default='monthly' help='Specify Interval for automatic invoice generation.' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
  • 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 (1)
  • write(self, vals)
    @api.multi

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    default=True string='Automatically Create Contracts At Sale Order Confirmation'
Public methods (0)

No public methods.

New fields (1)
  • create_contract_at_sale_order_confirmation Boolean
    readonly=False related='company_id.create_contract_at_sale_order_confirmation'
Public methods (0)

No public methods.

New fields (3)
  • contract_count Integer
    compute='_compute_contract_count'
  • is_contract Boolean
    compute='_compute_is_contract' string='Is a contract'
  • need_contract_creation Boolean
    compute='_compute_need_contract_creation'
Public methods (4)
  • action_confirm(self)
    @api.multi
    If we have a contract in the order, set it up
  • action_create_contract(self)
    @api.multi
  • action_show_contracts(self)
    @api.multi
  • check_contact_is_not_terminated(self)
    @api.constrains('state')

New fields (11)
  • auto_renew_interval Integer
    default=1 help='Renew every (Days/Week/Month/Year)' 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)')]
  • contract_id Many2one → contract.contract
    comodel_name='contract.contract' copy=False string='Contract'
  • contract_line_id Many2one → contract.line
    comodel_name='contract.line' copy=False required=False string='Contract Line to replace'
  • contract_template_id Many2one → contract.template
    comodel_name='contract.template' compute='_compute_contract_template_id' string='Contract Template'
  • date_end Date
    string='Date End'
  • date_start Date
    string='Date Start'
  • is_auto_renew Boolean
    default=False string='Auto Renew'
  • is_contract Boolean
    related='product_id.is_contract' string='Is a contract'
  • recurring_invoicing_type Selection
    copy=False default='pre-paid' help="Specify if process date is 'from' or 'to' invoicing date" string='Invoicing type' args: [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')]
  • recurring_rule_type Selection
    copy=False default='monthly' string='Invoice Every' args: [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('monthlylastday', 'Month(s) last day'), ('quarterly', 'Quarter(s)'), ('semesterly', 'Semester(s)'), ('yearly', 'Year(s)')]
Public methods (5)
  • check_contact_is_not_terminated(self)
    @api.constrains('contract_id')
  • create_contract_line(self, contract)
    @api.multi
  • invoice_line_create(self, invoice_id, qty)
    @api.multi
  • onchange_date_start(self)
    @api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type')
  • onchange_product(self)
    @api.onchange('product_id')
REPOSITORY
REPOSITORYOCA/contract
GIT
GIThttps://github.com/OCA/contract.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/contract/tree/10.0/product_contract
VERSION
VERSION 1.1.0
CATEGORY
CATEGORYContract Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), LasLabs
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), LasLabs
COMMITTERS
COMMITTERSRonald Portier, Pedro M. Baeza, GitHub, OCA Transbot, Dave Lasley, oca-travis, Weblate, OCA-git-bot
WEBSITE
WEBSITEhttps://github.com/oca/contract
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:19:55
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/contract:
    - contract
odoo/odoo:
    - base
    - account
    - base_setup
    - web_kanban
    - web
    - product
    - decimal_precision
    - mail
    - bus
    - web_tour
    - report
    - analytic
    - web_planner
    - sale
    - sales_team
    - procurement
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (1)
XML IDNameModelTypeStatus
product_template_form_contract_view account.invoice.select.contract product.template xpath Inherits product.product_template_form_view
Models touched (3)

New fields (2)
  • contract_template_id Many2one → account.analytic.contract
    comodel_name='account.analytic.contract' string='Contract Template'
  • is_contract Boolean
    args: 'Is a contract'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • action_confirm(self)
    @api.multi
    If we have a contract in the order, set it up

New fields (1)
  • contract_id Many2one → account.analytic.account
    comodel_name='account.analytic.account' string='Contract'
Public methods (1)
  • create_contract(self)
    @api.multi
    Create contract for sale order line. Should be called on confirmation of sale order.
STATUS
STATUSOpen migration PR - not merged yet for this version
REPOSITORY
REPOSITORYOCA/contract
PULL REQUEST
PULL REQUEST[19.0][MIG] product_contract (#1371)
STATUS
STATUSOpen migration PR - not merged yet for this version
REPOSITORY
REPOSITORYOCA/contract
PULL REQUEST
PULL REQUEST19.0 [MIG] product contract (#1336)