Coupons & Loyalty

loyalty
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/19.0/loyalty
VERSION
VERSION 1.0
CATEGORY
CATEGORYSales
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo S.A.
MAINTAINERS
MAINTAINERSOdoo S.A.
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Thibault Delavallée, Atul Patel, Géry Debongnie, Julien Castiaux, Victor Feyens, Tiffany Chang (tic), Rémy Voet (ryv), Gorash, Pierre Paridans, William Braeckman, Demesmaeker, Valentin Chevalier, alsh-odoo, Mylyna Hy, Victor Piryns (pivi), Levi Siuzdak (sile), Dylan Kiss (dyki), Sarah Bellefroid, kcv-odoo, dere-odoo, Louis Gobert, Junqi Wu, Xavier Luyckx (xlu), Ryan Cen, pish-odoo, Krzysztof Magusiak (krma), kkuj-odoo, Mahdi Alijani (malj), hatr-odoo, Dhwani Patel, assh-odoo, Elliot ELCO, steji, panj-odoo, Abdullah (abye)
WEBSITE
WEBSITE
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 01:51:41
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
    - uom
    - portal
    - http_routing
    - auth_signup
    - account
    - onboarding
    - analytic
    - digest
    - resource
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (23)
XML IDNameModelTypeStatus
gift_card_report gift_card_report ir.ui.view qweb New
gift_card_report_i18n gift_card_report_i18n ir.ui.view qweb New
loyalty_buttons loyalty_buttons ir.ui.view qweb Inherits portal.side_content
loyalty_card_history_template My Loyalty History ir.ui.view qweb New
loyalty_card_update_balance_form loyalty.card.update.balance.view.form loyalty.card.update.balance form New
loyalty_card_view_form loyalty.card.view.form loyalty.card form New
loyalty_card_view_search loyalty.card.view.search loyalty.card search New
loyalty_card_view_tree loyalty.card.view.list loyalty.card list New
loyalty_generate_wizard_view_form loyalty.generate.wizard.view.form loyalty.generate.wizard form New
loyalty_history_form loyalty.history.view.form loyalty.history form New
loyalty_mail_view_tree loyalty.mail.view.list loyalty.mail list New
loyalty_program_gift_ewallet_view_form loyalty.program.gift.ewallet.view.form loyalty.program form Inherits loyalty_program_view_form
loyalty_program_view_form loyalty.program.view.form loyalty.program form New
loyalty_program_view_search loyalty.program.view.search loyalty.program search New
loyalty_program_view_tree loyalty.program.view.list loyalty.program list New
loyalty_report loyalty_report ir.ui.view qweb New
loyalty_report_i18n loyalty_report_i18n ir.ui.view qweb New
loyalty_reward_view_form loyalty.reward.view.form loyalty.reward form New
loyalty_reward_view_kanban loyalty.reward.view.kanban loyalty.reward kanban New
loyalty_rule_view_form loyalty.rule.view.form loyalty.rule form New
loyalty_rule_view_kanban loyalty.rule.view.kanban loyalty.rule kanban New
portal_loyalty_history_breadcrumbs Portal layout : Loyalty History Lines ir.ui.view qweb Inherits portal.portal_breadcrumbs
res_partner_form res.partner.view.buttons res.partner div Inherits base.view_partner_form
Models touched (13)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (13)
  • active Boolean
    default=True
  • code Char
    default=<expr> required=True
  • company_id Many2one
    precompute=True related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • expiration_date Date
  • history_ids One2many → loyalty.history
    comodel_name='loyalty.history' inverse_name='card_id' readonly=True
  • partner_id Many2one → res.partner
    comodel_name='res.partner' index=True
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • points Float
    tracking=True
  • points_display Char
    compute='_compute_points_display'
  • program_id Many2one → loyalty.program
    comodel_name='loyalty.program' default=<expr> index='btree_not_null' ondelete='restrict'
  • program_type Selection
    related='program_id.program_type'
  • use_count Integer
    compute='_compute_use_count'
Public methods (4)
  • action_coupon_send(self)
    Open a window to compose an email, with the default template returned by `_get_default_template` message loaded by default
  • action_loyalty_update_balance(self)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (4)
  • card_id Many2one → loyalty.card
    comodel_name='loyalty.card' readonly=True required=True
  • description Char
    required=True
  • new_balance Float
  • old_balance Float
    related='card_id.points'
Public methods (1)
  • action_update_card_point(self)

New fields (12)
  • confirmation_message Char
    compute='_compute_confirmation_message'
  • coupon_qty Integer
    compute='_compute_coupon_qty' readonly=False store=True args: 'Quantity'
  • customer_ids Many2many → res.partner
    string='Customers' args: 'res.partner'
  • customer_tag_ids Many2many → res.partner.category
    string='Customer Tags' args: 'res.partner.category'
  • description Text
    string='Description'
  • mode Selection
    default='anonymous' required=True string='For' args: [('anonymous', 'Anonymous Customers'), ('selected', 'Selected Customers')]
  • points_granted Float
    default=1 required=True args: 'Grant'
  • points_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    default=<expr> required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • valid_until Date
  • will_send_mail Boolean
    compute='_compute_will_send_mail'
Public methods (1)
  • generate_coupons(self)

New fields (7)
  • card_id Many2one → loyalty.card
    comodel_name='loyalty.card' index=True ondelete='cascade' required=True
  • company_id Many2one
    related='card_id.company_id'
  • description Text
    required=True
  • issued Float
  • order_id Many2oneReference
    model_field='order_model' readonly=True
  • order_model Char
    readonly=True
  • used Float
Public methods (0)

No public methods.

New fields (5)
  • active Boolean
    default=True
  • mail_template_id Many2one → mail.template
    comodel_name='mail.template' domain=[('model', '=', 'loyalty.card')] ondelete='cascade' required=True string='Email Template'
  • points Float
  • program_id Many2one → loyalty.program
    comodel_name='loyalty.program' index=True ondelete='cascade' required=True
  • trigger Selection
    required=True selection=[('create', 'At Creation'), ('points_reach', 'When Reaching')] string='When'
Public methods (0)

No public methods.

New fields (29)
  • active Boolean
    default=True
  • applies_on Selection
    compute='_compute_from_program_type' default='current' readonly=False required=True selection=[('current', 'Current order'), ('future', 'Future orders'), ('both', 'Current & Future orders')] store=True
  • available_on Boolean
    help='Manage where your program should be available for use.' store=False string='Available On'
  • communication_plan_ids One2many → loyalty.mail
    comodel_name='loyalty.mail' compute='_compute_from_program_type' copy=True inverse_name='program_id' readonly=False store=True
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr> string='Company'
  • coupon_count Integer
    compute='_compute_coupon_count'
  • coupon_count_display Char
    compute='_compute_coupon_count_display' string='Items'
  • coupon_ids One2many → loyalty.card
    comodel_name='loyalty.card' inverse_name='program_id'
  • currency_id Many2one → res.currency
    comodel_name='res.currency' compute='_compute_currency_id' precompute=True readonly=False required=True store=True string='Currency'
  • currency_symbol Char
    related='currency_id.symbol'
  • date_from Date
    help='The start date is included in the validity period of this program' string='Start Date'
  • date_to Date
    help='The end date is included in the validity period of this program' string='End date'
  • is_nominative Boolean
    compute='_compute_is_nominative'
  • is_payment_program Boolean
    compute='_compute_is_payment_program'
  • limit_usage Boolean
    string='Limit Usage'
  • mail_template_id Many2one → mail.template
    comodel_name='mail.template' compute='_compute_mail_template_id' inverse='_inverse_mail_template_id' readonly=False string='Email template'
  • max_usage Integer
  • name Char
    required=True string='Program Name' translate=True
  • payment_program_discount_product_id Many2one → product.product
    comodel_name='product.product' compute='_compute_payment_program_discount_product_id' help='Product used in the sales order to apply the discount.' readonly=True string='Discount Product'
  • portal_point_name Char
    compute='_compute_portal_point_name' default='Points' readonly=False store=True translate=True
  • portal_visible Boolean
    default=False help='\n Show in web portal, PoS customer ticket, eCommerce checkout, the number of points available\n and used by reward.\n '
  • pricelist_ids Many2many → product.pricelist
    comodel_name='product.pricelist' domain="[('currency_id', '=', currency_id)]" help='This program is specific to this pricelist set.' string='Pricelist'
  • program_type Selection
    default='promotion' required=True selection=[('coupons', 'Coupons'), ('gift_card', 'Gift Card'), ('loyalty', 'Loyalty Cards'), ('promotion', 'Promotions'), ('ewallet', 'eWallet'), ('promo_code', 'Discount Code'), ('buy_x_get_y', 'Buy X Get Y'), ('next_order_coupons', 'Next Order Coupons')]
  • reward_ids One2many → loyalty.reward
    comodel_name='loyalty.reward' compute='_compute_from_program_type' copy=True inverse_name='program_id' readonly=False store=True string='Rewards'
  • rule_ids One2many → loyalty.rule
    comodel_name='loyalty.rule' compute='_compute_from_program_type' copy=True inverse_name='program_id' readonly=False store=True string='Conditional rules'
  • sequence Integer
    copy=False
  • total_order_count Integer
    compute='_compute_total_order_count' string='Total Order Count'
  • trigger Selection
    compute='_compute_from_program_type' help='\n Automatic: Customers will be eligible for a reward automatically in their cart.\n Use a code: Customers will be eligible for a reward if they enter a code.\n ' readonly=False selection=[('auto', 'Automatic'), ('with_code', 'Use a code')] store=True
  • trigger_product_ids Many2many
    readonly=False related='rule_ids.product_ids'
Public methods (6)
  • action_open_loyalty_cards(self)
  • create(self, vals_list)
    @api.model_create_multi
    trigger_product_ids will overwrite product ids defined in a loyalty rule in certain instances. Thus, it should be explicitly removed from an incoming vals dict unless, of course, it was actually a visible field.
  • create_from_template(self, template_id)
    @api.model
    Creates the program from the template id defined in `get_program_templates`. Returns an action leading to that new record.
  • default_get(self, fields)
    @api.model
  • get_program_templates(self)
    @api.model
    Returns the templates to be used for promotional programs.
  • write(self, vals)

New fields (29)
  • active Boolean
    default=True
  • all_discount_product_ids Many2many → product.product
    comodel_name='product.product' compute='_compute_all_discount_product_ids'
  • clear_wallet Boolean
    default=False
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • description Char
    compute='_compute_description' precompute=True readonly=False required=True store=True translate=True
  • discount Float
    default=10 string='Discount'
  • discount_applicability Selection
    default='order' selection=[('order', 'Order'), ('cheapest', 'Cheapest Product'), ('specific', 'Specific Products')]
  • discount_line_product_id Many2one → product.product
    comodel_name='product.product' copy=False help='Product used in the sales order to apply the discount. Each reward has its own product for reporting purpose' ondelete='restrict'
  • discount_max_amount Monetary
    help='This is the max amount this reward may discount, leave to 0 for no limit.' string='Max Discount'
  • discount_mode Selection
    default='percent' required=True selection=_get_discount_mode_select
  • discount_product_category_id Many2one → product.category
    comodel_name='product.category' string='Discounted Prod. Categories'
  • discount_product_domain Char
    default='[]'
  • discount_product_ids Many2many → product.product
    comodel_name='product.product' string='Discounted Products'
  • discount_product_tag_id Many2one → product.tag
    comodel_name='product.tag' string='Discounted Prod. Tag'
  • is_global_discount Boolean
    compute='_compute_is_global_discount'
  • multi_product Boolean
    compute='_compute_multi_product'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    comodel_name='loyalty.program' index=True ondelete='cascade' required=True
  • program_type Selection
    related='program_id.program_type'
  • required_points Float
    default=1 string='Points needed'
  • reward_product_domain Char
    compute='_compute_reward_product_domain' store=False
  • reward_product_id Many2one → product.product
    comodel_name='product.product' domain=[('type', '!=', 'combo')] string='Product'
  • reward_product_ids Many2many → product.product
    comodel_name='product.product' compute='_compute_multi_product' help='These are the products that can be claimed with this rule.' search='_search_reward_product_ids' string='Reward Products'
  • reward_product_qty Integer
    default=1
  • reward_product_tag_id Many2one → product.tag
    comodel_name='product.tag' string='Product Tag'
  • reward_product_uom_id Many2one → uom.uom
    comodel_name='uom.uom' compute='_compute_reward_product_uom_id'
  • reward_type Selection
    default='discount' required=True selection=[('product', 'Free Product'), ('discount', 'Discount')]
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields)
    @api.model
  • unlink(self)
  • update_field_translations(self, field_name, translations, source_lang='')
  • write(self, vals)

New fields (19)
  • active Boolean
    default=True
  • code Char
    compute='_compute_code' readonly=False store=True string='Discount code'
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • minimum_amount Monetary
    string='Minimum Purchase'
  • minimum_amount_tax_mode Selection
    default='incl' required=True selection=[('incl', 'tax included'), ('excl', 'tax excluded')]
  • minimum_qty Integer
    default=1 string='Minimum Quantity'
  • mode Selection
    compute='_compute_mode' readonly=False selection=[('auto', 'Automatic'), ('with_code', 'With a promotion code')] store=True string='Application'
  • product_category_id Many2one → product.category
    comodel_name='product.category' string='Categories'
  • product_domain Char
    default='[]'
  • product_ids Many2many → product.product
    comodel_name='product.product' string='Products'
  • product_tag_id Many2one → product.tag
    comodel_name='product.tag' string='Product Tag'
  • program_id Many2one → loyalty.program
    comodel_name='loyalty.program' index=True ondelete='cascade' required=True
  • program_type Selection
    related='program_id.program_type'
  • reward_point_amount Float
    default=1 string='Reward'
  • reward_point_mode Selection
    default='order' required=True selection=_get_reward_point_mode_selection
  • reward_point_name Char
    readonly=True related='program_id.portal_point_name'
  • reward_point_split Boolean
    default=False help="Whether to separate reward coupons per matched unit, only applies to 'future' programs and trigger mode per money spent or unit paid..." string='Split per unit'
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (1)
  • default_get(self, fields)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • action_archive(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (0)

No new fields.

Public methods (1)
  • create(self, vals_list)
    @api.model_create_multi
    Override of `product` to set a default image for gift cards.

New fields (1)
  • loyalty_card_count Integer
    compute='_compute_count_active_cards' compute_sudo=True groups='base.group_user' string='Active loyalty cards'
Public methods (1)
  • action_view_loyalty_cards(self)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/18.0/loyalty
VERSION
VERSION 1.0
CATEGORY
CATEGORYSales
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSRaphael Collet, Odoo Translation Bot, Martin Trigaux, Christophe Simonis, Atul Patel, Odoo Online, Victor Feyens, Prakash Prajapati, Tiffany Chang (tic), Gorash, Mathieu Duckerts-Antoine, Krzysztof Magusiak, hungbui, Demesmaeker, Weblate, alsh-odoo, Mylyna Hy, Levi Siuzdak (sile), Dylan Kiss (dyki), Anita (anko), Sarah Bellefroid, omra-odoo, Paul Stroobant, Youssef Bashandy, Ethan Vincent, Maryam Kia, Louis (loti), Julien Carion (juca), kcv-odoo, dere-odoo, Louis Gobert, Louis (wil), Junqi Wu, mathysPaul, mash, Ryan Cen, Manushi Shah, Pierre Pulinckx (pipu), pish-odoo, Mahdi Alijani (malj), Dhwani Patel, assh-odoo
WEBSITE
WEBSITE
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 01:25:54
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
    - uom
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - account
    - onboarding
    - analytic
    - digest
    - resource
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (23)
XML IDNameModelTypeStatus
gift_card_report gift_card_report ir.ui.view qweb New
gift_card_report_i18n gift_card_report_i18n ir.ui.view qweb New
loyalty_buttons loyalty_buttons ir.ui.view qweb Inherits portal.side_content
loyalty_card_history_template My Loyalty History ir.ui.view qweb New
loyalty_card_update_balance_form loyalty.card.update.balance.view.form loyalty.card.update.balance form New
loyalty_card_view_form loyalty.card.view.form loyalty.card form New
loyalty_card_view_search loyalty.card.view.search loyalty.card search New
loyalty_card_view_tree loyalty.card.view.list loyalty.card list New
loyalty_generate_wizard_view_form loyalty.generate.wizard.view.form loyalty.generate.wizard form New
loyalty_history_form loyalty.history.view.form loyalty.history form New
loyalty_mail_view_tree loyalty.mail.view.list loyalty.mail list New
loyalty_program_gift_ewallet_view_form loyalty.program.gift.ewallet.view.form loyalty.program form Inherits loyalty_program_view_form
loyalty_program_view_form loyalty.program.view.form loyalty.program form New
loyalty_program_view_search loyalty.program.view.search loyalty.program search New
loyalty_program_view_tree loyalty.program.view.list loyalty.program list New
loyalty_report loyalty_report ir.ui.view qweb New
loyalty_report_i18n loyalty_report_i18n ir.ui.view qweb New
loyalty_reward_view_form loyalty.reward.view.form loyalty.reward form New
loyalty_reward_view_kanban loyalty.reward.view.kanban loyalty.reward kanban New
loyalty_rule_view_form loyalty.rule.view.form loyalty.rule form New
loyalty_rule_view_kanban loyalty.rule.view.kanban loyalty.rule kanban New
portal_loyalty_history_breadcrumbs Portal layout : Loyalty History Lines ir.ui.view qweb Inherits portal.portal_breadcrumbs
res_partner_form res.partner.view.buttons res.partner div Inherits base.view_partner_form
Models touched (13)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (13)
  • active Boolean
    default=True
  • code Char
    default=<expr> required=True
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • expiration_date Date
  • history_ids One2many → loyalty.history
    comodel_name='loyalty.history' inverse_name='card_id' readonly=True
  • partner_id Many2one → res.partner
    index=True args: 'res.partner'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • points Float
    tracking=True
  • points_display Char
    compute='_compute_points_display'
  • program_id Many2one → loyalty.program
    default=<expr> ondelete='restrict' args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • use_count Integer
    compute='_compute_use_count'
Public methods (4)
  • action_coupon_send(self)
    Open a window to compose an email, with the default template returned by `_get_default_template` message loaded by default
  • action_loyalty_update_balance(self)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (4)
  • card_id Many2one → loyalty.card
    comodel_name='loyalty.card' readonly=True required=True
  • description Char
    required=True
  • new_balance Float
  • old_balance Float
    related='card_id.points'
Public methods (1)
  • action_update_card_point(self)

New fields (12)
  • confirmation_message Char
    compute='_compute_confirmation_message'
  • coupon_qty Integer
    compute='_compute_coupon_qty' readonly=False store=True args: 'Quantity'
  • customer_ids Many2many → res.partner
    string='Customers' args: 'res.partner'
  • customer_tag_ids Many2many → res.partner.category
    string='Customer Tags' args: 'res.partner.category'
  • description Text
    string='Description'
  • mode Selection
    default='anonymous' required=True string='For' args: [('anonymous', 'Anonymous Customers'), ('selected', 'Selected Customers')]
  • points_granted Float
    default=1 required=True args: 'Grant'
  • points_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    default=<expr> required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • valid_until Date
  • will_send_mail Boolean
    compute='_compute_will_send_mail'
Public methods (1)
  • generate_coupons(self)

New fields (7)
  • card_id Many2one → loyalty.card
    comodel_name='loyalty.card' ondelete='cascade' required=True
  • company_id Many2one
    related='card_id.company_id'
  • description Text
    required=True
  • issued Float
  • order_id Many2oneReference
    model_field='order_model' readonly=True
  • order_model Char
    readonly=True
  • used Float
Public methods (0)

No public methods.

New fields (5)
  • active Boolean
    default=True
  • mail_template_id Many2one → mail.template
    domain=[('model', '=', 'loyalty.card')] ondelete='cascade' required=True string='Email Template' args: 'mail.template'
  • points Float
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • trigger Selection
    required=True string='When' args: [('create', 'At Creation'), ('points_reach', 'When Reaching')]
Public methods (0)

No public methods.

New fields (29)
  • active Boolean
    default=True
  • applies_on Selection
    compute='_compute_from_program_type' default='current' readonly=False required=True store=True args: [('current', 'Current order'), ('future', 'Future orders'), ('both', 'Current & Future orders')]
  • available_on Boolean
    help='\n Manage where your program should be available for use.\n ' store=False args: 'Available On'
  • communication_plan_ids One2many → loyalty.mail
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.mail', 'program_id'
  • company_id Many2one → res.company
    default=<expr> args: 'res.company', 'Company'
  • coupon_count Integer
    compute='_compute_coupon_count'
  • coupon_count_display Char
    compute='_compute_coupon_count_display' string='Items'
  • coupon_ids One2many → loyalty.card
    args: 'loyalty.card', 'program_id'
  • currency_id Many2one → res.currency
    compute='_compute_currency_id' precompute=True readonly=False required=True store=True args: 'res.currency', 'Currency'
  • currency_symbol Char
    related='currency_id.symbol'
  • date_from Date
    help='The start date is included in the validity period of this program' string='Start Date'
  • date_to Date
    help='The end date is included in the validity period of this program' string='End date'
  • is_nominative Boolean
    compute='_compute_is_nominative'
  • is_payment_program Boolean
    compute='_compute_is_payment_program'
  • limit_usage Boolean
    string='Limit Usage'
  • mail_template_id Many2one → mail.template
    compute='_compute_mail_template_id' inverse='_inverse_mail_template_id' readonly=False string='Email template' args: 'mail.template'
  • max_usage Integer
  • name Char
    required=True translate=True args: 'Program Name'
  • payment_program_discount_product_id Many2one → product.product
    compute='_compute_payment_program_discount_product_id' help='Product used in the sales order to apply the discount.' readonly=True string='Discount Product' args: 'product.product'
  • portal_point_name Char
    compute='_compute_portal_point_name' default='Points' readonly=False store=True translate=True
  • portal_visible Boolean
    default=False help='\n Show in web portal, PoS customer ticket, eCommerce checkout, the number of points available and used by reward.\n '
  • pricelist_ids Many2many → product.pricelist
    comodel_name='product.pricelist' domain="[('currency_id', '=', currency_id)]" help='This program is specific to this pricelist set.' string='Pricelist'
  • program_type Selection
    default='promotion' required=True args: [('coupons', 'Coupons'), ('gift_card', 'Gift Card'), ('loyalty', 'Loyalty Cards'), ('promotion', 'Promotions'), ('ewallet', 'eWallet'), ('promo_code', 'Discount Code'), ('buy_x_get_y', 'Buy X Get Y'), ('next_order_coupons', 'Next Order Coupons')]
  • reward_ids One2many → loyalty.reward
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.reward', 'program_id', 'Rewards'
  • rule_ids One2many → loyalty.rule
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.rule', 'program_id', 'Conditional rules'
  • sequence Integer
    copy=False
  • total_order_count Integer
    compute='_compute_total_order_count' args: 'Total Order Count'
  • trigger Selection
    compute='_compute_from_program_type' help='\n Automatic: Customers will be eligible for a reward automatically in their cart.\n Use a code: Customers will be eligible for a reward if they enter a code.\n ' readonly=False store=True args: [('auto', 'Automatic'), ('with_code', 'Use a code')]
  • trigger_product_ids Many2many
    readonly=False related='rule_ids.product_ids'
Public methods (7)
  • action_open_loyalty_cards(self)
  • create(self, vals_list)
    @api.model_create_multi
    trigger_product_ids will overwrite product ids defined in a loyalty rule in certain instances. Thus, it should be explicitly removed from an incoming vals dict unless, of course, it was actually a visible field.
  • create_from_template(self, template_id)
    @api.model
    Creates the program from the template id defined in `get_program_templates`. Returns an action leading to that new record.
  • default_get(self, fields_list)
    @api.model
  • get_program_templates(self)
    @api.model
    Returns the templates to be used for promotional programs.
  • toggle_active(self)
  • write(self, vals)

New fields (30)
  • active Boolean
    default=True
  • all_discount_product_ids Many2many → product.product
    compute='_compute_all_discount_product_ids' args: 'product.product'
  • clear_wallet Boolean
    default=False
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • description Char
    compute='_compute_description' precompute=True readonly=False required=True store=True translate=True
  • discount Float
    default=10 args: 'Discount'
  • discount_applicability Selection
    default='order' args: [('order', 'Order'), ('cheapest', 'Cheapest Product'), ('specific', 'Specific Products')]
  • discount_line_product_id Many2one → product.product
    copy=False help='Product used in the sales order to apply the discount. Each reward has its own product for reporting purpose' ondelete='restrict' args: 'product.product'
  • discount_max_amount Monetary
    help='This is the max amount this reward may discount, leave to 0 for no limit.' args: 'Max Discount', 'currency_id'
  • discount_mode Selection
    default='percent' required=True selection=_get_discount_mode_select
  • discount_product_category_id Many2one → product.category
    string='Discounted Prod. Categories' args: 'product.category'
  • discount_product_domain Char
    default='[]'
  • discount_product_ids Many2many → product.product
    string='Discounted Products' args: 'product.product'
  • discount_product_tag_id Many2one → product.tag
    string='Discounted Prod. Tag' args: 'product.tag'
  • is_global_discount Boolean
    compute='_compute_is_global_discount'
  • multi_product Boolean
    compute='_compute_multi_product'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • required_points Float
    default=1 args: 'Points needed'
  • reward_product_domain Char
    compute='_compute_reward_product_domain' store=False
  • reward_product_id Many2one → product.product
    domain=[('type', '!=', 'combo')] string='Product' args: 'product.product'
  • reward_product_ids Many2many → product.product
    compute='_compute_multi_product' help='These are the products that can be claimed with this rule.' search='_search_reward_product_ids' string='Reward Products' args: 'product.product'
  • reward_product_qty Integer
    default=1
  • reward_product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • reward_product_uom_id Many2one → uom.uom
    compute='_compute_reward_product_uom_id' args: 'uom.uom'
  • reward_type Selection
    default='discount' required=True args: [('product', 'Free Product'), ('discount', 'Discount')]
  • tax_ids Many2many → account.tax
    comodel_name='account.tax' domain="[('type_tax_use', '=', 'sale'), ('company_id', '=', company_id)]" help='Taxes to add on the discount line.' string='Taxes'
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields_list)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (19)
  • active Boolean
    default=True
  • code Char
    compute='_compute_code' readonly=False store=True string='Discount code'
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • minimum_amount Monetary
    args: 'Minimum Purchase', 'currency_id'
  • minimum_amount_tax_mode Selection
    default='incl' required=True selection=[('incl', 'tax included'), ('excl', 'tax excluded')]
  • minimum_qty Integer
    default=1 args: 'Minimum Quantity'
  • mode Selection
    compute='_compute_mode' readonly=False store=True string='Application' args: [('auto', 'Automatic'), ('with_code', 'With a promotion code')]
  • product_category_id Many2one → product.category
    string='Categories' args: 'product.category'
  • product_domain Char
    default='[]'
  • product_ids Many2many → product.product
    string='Products' args: 'product.product'
  • product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • reward_point_amount Float
    default=1 string='Reward'
  • reward_point_mode Selection
    default='order' required=True selection=_get_reward_point_mode_selection
  • reward_point_name Char
    readonly=True related='program_id.portal_point_name'
  • reward_point_split Boolean
    default=False help="Whether to separate reward coupons per matched unit, only applies to 'future' programs and trigger mode per money spent or unit paid.." string='Split per unit'
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (1)
  • default_get(self, fields_list)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • action_archive(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • loyalty_card_count Integer
    compute='_compute_count_active_cards' compute_sudo=True groups='base.group_user' string='Active loyalty cards'
Public methods (1)
  • action_view_loyalty_cards(self)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/17.0/loyalty
VERSION
VERSION 1.0
CATEGORY
CATEGORYSales
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSOdoo Translation Bot, Martin Trigaux, Fabien Pinckaers, Thibault Delavallée, Christophe Simonis, Atul Patel, Aaron Bohy, Odoo Online, Jorge Pinna Puissant, Victor Feyens, Joseph Caburnay, Florent de Labarre, Samuel Degueldre, Nasreddin Boulif (bon), Prakash Prajapati, Tiffany Chang (tic), Rémy Voet (ryv), Gorash, Pierre Paridans, William Braeckman, roen-odoo, Jacky (trj), mafo-odoo, hungbui, Nshimiyimana Séna, luvi, rhe-odoo, niyasraphy, David Monnom (moda), Thomas Lefebvre (thle), alsh-odoo, Louis Wicket (wil), Mylyna Hy, althaf shaik, Valentin Vallaeys (vava), Levi Siuzdak (sile), Dylan Kiss (dyki), Bruno Boi, FrancoisGe, Michael (mcm), Horacio Tellez, Valeriya(vchu), paso-odoo, Anita (anko), Brieuc-brd, Sarah Bellefroid, Theo VINCENT (thvi), Mahdi Cheikh Rouhou (macr), Paul Stroobant, stefanorigano (SRI), Youssef Bashandy, Ethan Vincent, vava-odoo, Julien Carion (juca), kcv-odoo, dere-odoo, Chrysanthe (chgo), Louis (wil), Junqi Wu, Loukas Wets (lowe), Ryan Cen, Manushi Shah, luve-odoo, nikj-odoo, Dhwani Patel
WEBSITE
WEBSITE
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 01:02:05
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (18)
XML IDNameModelTypeStatus
gift_card_report gift_card_report ir.ui.view qweb New
gift_card_report_i18n gift_card_report_i18n ir.ui.view qweb New
loyalty_card_view_form loyalty.card.view.form loyalty.card form New
loyalty_card_view_search loyalty.card.view.search loyalty.card search New
loyalty_card_view_tree loyalty.card.view.tree loyalty.card tree New
loyalty_generate_wizard_view_form loyalty.generate.wizard.view.form loyalty.generate.wizard form New
loyalty_mail_view_tree loyalty.mail.view.tree loyalty.mail tree New
loyalty_program_gift_ewallet_view_form loyalty.program.gift.ewallet.view.form loyalty.program form Inherits loyalty_program_view_form
loyalty_program_view_form loyalty.program.view.form loyalty.program form New
loyalty_program_view_search loyalty.program.view.search loyalty.program search New
loyalty_program_view_tree loyalty.program.view.tree loyalty.program tree New
loyalty_report loyalty_report ir.ui.view qweb New
loyalty_report_i18n loyalty_report_i18n ir.ui.view qweb New
loyalty_reward_view_form loyalty.reward.view.form loyalty.reward form New
loyalty_reward_view_kanban loyalty.reward.view.kanban loyalty.reward kanban New
loyalty_rule_view_form loyalty.rule.view.form loyalty.rule form New
loyalty_rule_view_kanban loyalty.rule.view.kanban loyalty.rule kanban New
res_partner_form res.partner.view.buttons res.partner div Inherits base.view_partner_form
Models touched (10)

New fields (11)
  • code Char
    default=<expr> required=True
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • expiration_date Date
  • partner_id Many2one → res.partner
    index=True args: 'res.partner'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • points Float
    tracking=True
  • points_display Char
    compute='_compute_points_display'
  • program_id Many2one → loyalty.program
    default=<expr> ondelete='restrict' args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • use_count Integer
    compute='_compute_use_count'
Public methods (3)
  • action_coupon_send(self)
    Open a window to compose an email, with the default template returned by `_get_default_template` message loaded by default
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (10)
  • coupon_qty Integer
    compute='_compute_coupon_qty' readonly=False store=True args: 'Quantity'
  • customer_ids Many2many → res.partner
    string='Customers' args: 'res.partner'
  • customer_tag_ids Many2many → res.partner.category
    string='Customer Tags' args: 'res.partner.category'
  • mode Selection
    default='anonymous' required=True string='For' args: [('anonymous', 'Anonymous Customers'), ('selected', 'Selected Customers')]
  • points_granted Float
    default=1 required=True args: 'Grant'
  • points_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    default=<expr> required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • valid_until Date
  • will_send_mail Boolean
    compute='_compute_will_send_mail'
Public methods (1)
  • generate_coupons(self)

New fields (5)
  • active Boolean
    default=True
  • mail_template_id Many2one → mail.template
    domain=[('model', '=', 'loyalty.card')] ondelete='cascade' required=True string='Email Template' args: 'mail.template'
  • points Float
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • trigger Selection
    required=True string='When' args: [('create', 'At Creation'), ('points_reach', 'When Reaching')]
Public methods (0)

No public methods.

New fields (29)
  • active Boolean
    default=True
  • applies_on Selection
    compute='_compute_from_program_type' default='current' readonly=False required=True store=True args: [('current', 'Current order'), ('future', 'Future orders'), ('both', 'Current & Future orders')]
  • available_on Boolean
    help='\n Manage where your program should be available for use.\n ' store=False args: 'Available On'
  • communication_plan_ids One2many → loyalty.mail
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.mail', 'program_id'
  • company_id Many2one → res.company
    default=<expr> args: 'res.company', 'Company'
  • coupon_count Integer
    compute='_compute_coupon_count'
  • coupon_count_display Char
    compute='_compute_coupon_count_display' string='Items'
  • coupon_ids One2many → loyalty.card
    args: 'loyalty.card', 'program_id'
  • currency_id Many2one → res.currency
    compute='_compute_currency_id' precompute=True readonly=False required=True store=True args: 'res.currency', 'Currency'
  • currency_symbol Char
    related='currency_id.symbol'
  • date_from Date
    help='The start date is included in the validity period of this program' string='Start Date'
  • date_to Date
    help='The end date is included in the validity period of this program' string='End date'
  • is_nominative Boolean
    compute='_compute_is_nominative'
  • is_payment_program Boolean
    compute='_compute_is_payment_program'
  • limit_usage Boolean
    string='Limit Usage'
  • mail_template_id Many2one → mail.template
    compute='_compute_mail_template_id' inverse='_inverse_mail_template_id' readonly=False string='Email template' args: 'mail.template'
  • max_usage Integer
  • name Char
    required=True translate=True args: 'Program Name'
  • payment_program_discount_product_id Many2one → product.product
    compute='_compute_payment_program_discount_product_id' help='Product used in the sales order to apply the discount.' readonly=True string='Discount Product' args: 'product.product'
  • portal_point_name Char
    compute='_compute_portal_point_name' default='Points' readonly=False store=True translate=True
  • portal_visible Boolean
    default=False help='\n Show in web portal, PoS customer ticket, eCommerce checkout, the number of points available and used by reward.\n '
  • pricelist_ids Many2many → product.pricelist
    domain="[('currency_id', '=', currency_id)]" string='Pricelist' args: 'product.pricelist'
  • program_type Selection
    default='promotion' required=True args: [('coupons', 'Coupons'), ('gift_card', 'Gift Card'), ('loyalty', 'Loyalty Cards'), ('promotion', 'Promotions'), ('ewallet', 'eWallet'), ('promo_code', 'Discount Code'), ('buy_x_get_y', 'Buy X Get Y'), ('next_order_coupons', 'Next Order Coupons')]
  • reward_ids One2many → loyalty.reward
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.reward', 'program_id', 'Rewards'
  • rule_ids One2many → loyalty.rule
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.rule', 'program_id', 'Conditional rules'
  • sequence Integer
    copy=False
  • total_order_count Integer
    compute='_compute_total_order_count' args: 'Total Order Count'
  • trigger Selection
    compute='_compute_from_program_type' help='\n Automatic: Customers will be eligible for a reward automatically in their cart.\n Use a code: Customers will be eligible for a reward if they enter a code.\n ' readonly=False store=True args: [('auto', 'Automatic'), ('with_code', 'Use a code')]
  • trigger_product_ids Many2many
    readonly=False related='rule_ids.product_ids'
Public methods (6)
  • action_open_loyalty_cards(self)
  • create(self, vals_list)
    @api.model_create_multi
    trigger_product_ids will overwrite product ids defined in a loyalty rule in certain instances. Thus, it should be explicitly removed from an incoming vals dict unless, of course, it was actually a visible field.
  • create_from_template(self, template_id)
    @api.model
    Creates the program from the template id defined in `get_program_templates`. Returns an action leading to that new record.
  • get_program_templates(self)
    @api.model
    Returns the templates to be used for promotional programs.
  • toggle_active(self)
  • write(self, vals)

New fields (29)
  • active Boolean
    default=True
  • all_discount_product_ids Many2many → product.product
    compute='_compute_all_discount_product_ids' args: 'product.product'
  • clear_wallet Boolean
    default=False
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • description Char
    compute='_compute_description' readonly=False store=True translate=True
  • discount Float
    default=10 args: 'Discount'
  • discount_applicability Selection
    default='order' args: [('order', 'Order'), ('cheapest', 'Cheapest Product'), ('specific', 'Specific Products')]
  • discount_line_product_id Many2one → product.product
    copy=False help='Product used in the sales order to apply the discount. Each reward has its own product for reporting purpose' ondelete='restrict' args: 'product.product'
  • discount_max_amount Monetary
    help='This is the max amount this reward may discount, leave to 0 for no limit.' args: 'Max Discount', 'currency_id'
  • discount_mode Selection
    default='percent' required=True selection=_get_discount_mode_select
  • discount_product_category_id Many2one → product.category
    string='Discounted Prod. Categories' args: 'product.category'
  • discount_product_domain Char
    default='[]'
  • discount_product_ids Many2many → product.product
    string='Discounted Products' args: 'product.product'
  • discount_product_tag_id Many2one → product.tag
    string='Discounted Prod. Tag' args: 'product.tag'
  • is_global_discount Boolean
    compute='_compute_is_global_discount'
  • multi_product Boolean
    compute='_compute_multi_product'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • required_points Float
    default=1 args: 'Points needed'
  • reward_product_domain Char
    compute='_compute_reward_product_domain' store=False
  • reward_product_id Many2one → product.product
    string='Product' args: 'product.product'
  • reward_product_ids Many2many → product.product
    compute='_compute_multi_product' help='These are the products that can be claimed with this rule.' search='_search_reward_product_ids' string='Reward Products' args: 'product.product'
  • reward_product_qty Integer
    default=1
  • reward_product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • reward_product_uom_id Many2one → uom.uom
    compute='_compute_reward_product_uom_id' args: 'uom.uom'
  • reward_type Selection
    default='discount' required=True args: [('product', 'Free Product'), ('discount', 'Discount')]
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (4)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields_list)
    @api.model
  • unlink(self)
  • write(self, vals)

New fields (19)
  • active Boolean
    default=True
  • code Char
    compute='_compute_code' readonly=False store=True string='Discount code'
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • minimum_amount Monetary
    args: 'Minimum Purchase', 'currency_id'
  • minimum_amount_tax_mode Selection
    default='incl' required=True args: [('incl', 'Included'), ('excl', 'Excluded')]
  • minimum_qty Integer
    default=1 args: 'Minimum Quantity'
  • mode Selection
    compute='_compute_mode' readonly=False store=True string='Application' args: [('auto', 'Automatic'), ('with_code', 'With a promotion code')]
  • product_category_id Many2one → product.category
    string='Categories' args: 'product.category'
  • product_domain Char
    default='[]'
  • product_ids Many2many → product.product
    string='Products' args: 'product.product'
  • product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • reward_point_amount Float
    default=1 string='Reward'
  • reward_point_mode Selection
    default='order' required=True selection=_get_reward_point_mode_selection
  • reward_point_name Char
    readonly=True related='program_id.portal_point_name'
  • reward_point_split Boolean
    default=False help="Whether to separate reward coupons per matched unit, only applies to 'future' programs and trigger mode per money spent or unit paid.." string='Split per unit'
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (1)
  • default_get(self, fields_list)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • action_archive(self)

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (1)
  • loyalty_card_count Integer
    compute='_compute_count_active_cards' compute_sudo=True groups='base.group_user' string='Active loyalty cards'
Public methods (1)
  • action_view_loyalty_cards(self)
REPOSITORY
REPOSITORYodoo/odoo
GIT
GIThttps://github.com/odoo/odoo.git
GIT FOLDER
GIT FOLDERhttps://github.com/odoo/odoo/tree/16.0/loyalty
VERSION
VERSION 1.0
CATEGORY
CATEGORYSales
LICENSE
LICENSELGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORS
MAINTAINERS
MAINTAINERS
COMMITTERS
COMMITTERSOdoo Translation Bot, Martin Trigaux, Fabien Pinckaers, Thibault Delavallée, Denis Ledoux, Christophe Simonis, SEINLET Nicolas, Pierre Masereel, Aurélien Warnon, Romeo Fragomeli, Victor Feyens, Joseph Caburnay, Florent de Labarre, Nasreddin Boulif (bon), Prakash Prajapati, Tiffany Chang (tic), Gorash, William Braeckman, roen-odoo, Jacky (trj), mafo-odoo, hungbui, Nshimiyimana Séna, Valentin Chevalier, Roy Le, rhe-odoo, niyasraphy, David Monnom (moda), Louis Wicket (wil), Mylyna Hy, althaf shaik, Valentin Vallaeys (vava), Levi Siuzdak (sile), Michael (mcm), Horacio Tellez, paso-odoo, Anita (anko), Brieuc-brd, Sarah Bellefroid, Mahdi Cheikh Rouhou (macr), Youssef Bashandy, Ethan Vincent, vava-odoo, kcv-odoo, dere-odoo, Martin Trigaux (mat), Ryan Cen, Manushi Shah, William Braeckman (wbr)
WEBSITE
WEBSITE
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:40:47
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (17)
XML IDNameModelTypeStatus
gift_card_report gift_card_report ir.ui.view qweb New
gift_card_report_i18n gift_card_report_i18n ir.ui.view qweb New
loyalty_card_view_form loyalty.card.view.form loyalty.card form New
loyalty_card_view_search loyalty.card.view.search loyalty.card search New
loyalty_card_view_tree loyalty.card.view.tree loyalty.card tree New
loyalty_generate_wizard_view_form loyalty.generate.wizard.view.form loyalty.generate.wizard form New
loyalty_mail_view_tree loyalty.mail.view.tree loyalty.mail tree New
loyalty_program_gift_ewallet_view_form loyalty.program.gift.ewallet.view.form loyalty.program form Inherits loyalty_program_view_form
loyalty_program_view_form loyalty.program.view.form loyalty.program form New
loyalty_program_view_search loyalty.program.view.search loyalty.program search New
loyalty_program_view_tree loyalty.program.view.tree loyalty.program tree New
loyalty_report loyalty_report ir.ui.view qweb New
loyalty_report_i18n loyalty_report_i18n ir.ui.view qweb New
loyalty_reward_view_form loyalty.reward.view.form loyalty.reward form New
loyalty_reward_view_kanban loyalty.reward.view.kanban loyalty.reward kanban New
loyalty_rule_view_form loyalty.rule.view.form loyalty.rule form New
loyalty_rule_view_kanban loyalty.rule.view.kanban loyalty.rule kanban New
Models touched (8)

New fields (11)
  • code Char
    default=<expr> required=True
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • expiration_date Date
  • partner_id Many2one → res.partner
    index=True args: 'res.partner'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • points Float
    tracking=True
  • points_display Char
    compute='_compute_points_display'
  • program_id Many2one → loyalty.program
    default=<expr> ondelete='restrict' args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • use_count Integer
    compute='_compute_use_count'
Public methods (4)
  • action_coupon_send(self)
    Open a window to compose an email, with the default template returned by `_get_default_template` message loaded by default
  • create(self, vals_list)
    @api.model_create_multi
  • name_get(self)
  • write(self, vals)

New fields (10)
  • coupon_qty Integer
    compute='_compute_coupon_qty' readonly=False store=True args: 'Quantity'
  • customer_ids Many2many → res.partner
    string='Customers' args: 'res.partner'
  • customer_tag_ids Many2many → res.partner.category
    string='Customer Tags' args: 'res.partner.category'
  • mode Selection
    default='anonymous' required=True string='For' args: [('anonymous', 'Anonymous Customers'), ('selected', 'Selected Customers')]
  • points_granted Float
    default=1 required=True args: 'Grant'
  • points_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    default=<expr> required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • valid_until Date
  • will_send_mail Boolean
    compute='_compute_will_send_mail'
Public methods (1)
  • generate_coupons(self)

New fields (5)
  • active Boolean
    default=True
  • mail_template_id Many2one → mail.template
    domain=[('model', '=', 'loyalty.card')] required=True string='Email Template' args: 'mail.template'
  • points Float
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • trigger Selection
    required=True string='When' args: [('create', 'At Creation'), ('points_reach', 'When Reaching')]
Public methods (0)

No public methods.

New fields (27)
  • active Boolean
    default=True
  • applies_on Selection
    compute='_compute_from_program_type' default='current' readonly=False required=True store=True args: [('current', 'Current order'), ('future', 'Future orders'), ('both', 'Current & Future orders')]
  • available_on Boolean
    help='\n Manage where your program should be available for use.\n ' store=False args: 'Available On'
  • communication_plan_ids One2many → loyalty.mail
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.mail', 'program_id'
  • company_id Many2one → res.company
    default=<expr> args: 'res.company', 'Company'
  • coupon_count Integer
    compute='_compute_coupon_count'
  • coupon_count_display Char
    compute='_compute_coupon_count_display' string='Items'
  • coupon_ids One2many → loyalty.card
    args: 'loyalty.card', 'program_id'
  • currency_id Many2one → res.currency
    compute='_compute_currency_id' precompute=True readonly=False required=True store=True args: 'res.currency', 'Currency'
  • currency_symbol Char
    related='currency_id.symbol'
  • date_to Date
    string='Validity'
  • is_nominative Boolean
    compute='_compute_is_nominative'
  • is_payment_program Boolean
    compute='_compute_is_payment_program'
  • limit_usage Boolean
    string='Limit Usage'
  • mail_template_id Many2one → mail.template
    compute='_compute_mail_template_id' inverse='_inverse_mail_template_id' readonly=False string='Email template' args: 'mail.template'
  • max_usage Integer
  • name Char
    required=True translate=True args: 'Program Name'
  • payment_program_discount_product_id Many2one → product.product
    compute='_compute_payment_program_discount_product_id' help='Product used in the sales order to apply the discount.' readonly=True string='Discount Product' args: 'product.product'
  • portal_point_name Char
    compute='_compute_portal_point_name' default='Points' readonly=False store=True translate=True
  • portal_visible Boolean
    default=False help='\n Show in web portal, PoS customer ticket, eCommerce checkout, the number of points available and used by reward.\n '
  • program_type Selection
    default='promotion' required=True args: [('coupons', 'Coupons'), ('gift_card', 'Gift Card'), ('loyalty', 'Loyalty Cards'), ('promotion', 'Promotions'), ('ewallet', 'eWallet'), ('promo_code', 'Discount Code'), ('buy_x_get_y', 'Buy X Get Y'), ('next_order_coupons', 'Next Order Coupons')]
  • reward_ids One2many → loyalty.reward
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.reward', 'program_id', 'Rewards'
  • rule_ids One2many → loyalty.rule
    compute='_compute_from_program_type' copy=True readonly=False store=True args: 'loyalty.rule', 'program_id', 'Conditional rules'
  • sequence Integer
    copy=False
  • total_order_count Integer
    compute='_compute_total_order_count' args: 'Total Order Count'
  • trigger Selection
    compute='_compute_from_program_type' help='\n Automatic: Customers will be eligible for a reward automatically in their cart.\n Use a code: Customers will be eligible for a reward if they enter a code.\n ' readonly=False store=True args: [('auto', 'Automatic'), ('with_code', 'Use a code')]
  • trigger_product_ids Many2many
    readonly=False related='rule_ids.product_ids'
Public methods (6)
  • action_open_loyalty_cards(self)
  • create(self, vals_list)
    @api.model_create_multi
    trigger_product_ids will overwrite product ids defined in a loyalty rule in certain instances. Thus, it should be explicitly removed from an incoming vals dict unless, of course, it was actually a visible field.
  • create_from_template(self, template_id)
    @api.model
    Creates the program from the template id defined in `get_program_templates`. Returns an action leading to that new record.
  • get_program_templates(self)
    @api.model
    Returns the templates to be used for promotional programs.
  • toggle_active(self)
  • write(self, vals)

New fields (29)
  • active Boolean
    default=True
  • all_discount_product_ids Many2many → product.product
    compute='_compute_all_discount_product_ids' args: 'product.product'
  • clear_wallet Boolean
    default=False
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • description Char
    compute='_compute_description' readonly=False store=True translate=True
  • discount Float
    default=10 args: 'Discount'
  • discount_applicability Selection
    default='order' args: [('order', 'Order'), ('cheapest', 'Cheapest Product'), ('specific', 'Specific Products')]
  • discount_line_product_id Many2one → product.product
    copy=False help='Product used in the sales order to apply the discount. Each reward has its own product for reporting purpose' ondelete='restrict' args: 'product.product'
  • discount_max_amount Monetary
    help='This is the max amount this reward may discount, leave to 0 for no limit.' args: 'Max Discount', 'currency_id'
  • discount_mode Selection
    default='percent' required=True selection=_get_discount_mode_select
  • discount_product_category_id Many2one → product.category
    string='Discounted Prod. Categories' args: 'product.category'
  • discount_product_domain Char
    default='[]'
  • discount_product_ids Many2many → product.product
    string='Discounted Products' args: 'product.product'
  • discount_product_tag_id Many2one → product.tag
    string='Discounted Prod. Tag' args: 'product.tag'
  • is_global_discount Boolean
    compute='_compute_is_global_discount'
  • multi_product Boolean
    compute='_compute_multi_product'
  • point_name Char
    readonly=True related='program_id.portal_point_name'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • required_points Float
    default=1 args: 'Points needed'
  • reward_product_domain Char
    compute='_compute_reward_product_domain' store=False
  • reward_product_id Many2one → product.product
    string='Product' args: 'product.product'
  • reward_product_ids Many2many → product.product
    compute='_compute_multi_product' help='These are the products that can be claimed with this rule.' search='_search_reward_product_ids' string='Reward Products' args: 'product.product'
  • reward_product_qty Integer
    default=1
  • reward_product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • reward_product_uom_id Many2one → uom.uom
    compute='_compute_reward_product_uom_id' args: 'uom.uom'
  • reward_type Selection
    default='discount' required=True args: [('product', 'Free Product'), ('discount', 'Discount')]
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • default_get(self, fields_list)
    @api.model
  • name_get(self)
  • unlink(self)
  • write(self, vals)

New fields (19)
  • active Boolean
    default=True
  • code Char
    compute='_compute_code' readonly=False store=True string='Discount code'
  • company_id Many2one
    related='program_id.company_id' store=True
  • currency_id Many2one
    related='program_id.currency_id'
  • minimum_amount Monetary
    args: 'Minimum Purchase', 'currency_id'
  • minimum_amount_tax_mode Selection
    default='incl' required=True args: [('incl', 'Included'), ('excl', 'Excluded')]
  • minimum_qty Integer
    default=1 args: 'Minimum Quantity'
  • mode Selection
    compute='_compute_mode' readonly=False store=True string='Application' args: [('auto', 'Automatic'), ('with_code', 'With a promotion code')]
  • product_category_id Many2one → product.category
    string='Categories' args: 'product.category'
  • product_domain Char
    default='[]'
  • product_ids Many2many → product.product
    string='Products' args: 'product.product'
  • product_tag_id Many2one → product.tag
    string='Product Tag' args: 'product.tag'
  • program_id Many2one → loyalty.program
    ondelete='cascade' required=True args: 'loyalty.program'
  • program_type Selection
    related='program_id.program_type'
  • reward_point_amount Float
    default=1 string='Reward'
  • reward_point_mode Selection
    default='order' required=True selection=_get_reward_point_mode_selection
  • reward_point_name Char
    readonly=True related='program_id.portal_point_name'
  • reward_point_split Boolean
    default=False help="Whether to separate reward coupons per matched unit, only applies to 'future' programs and trigger mode per money spent or unit paid.." string='Split per unit'
  • user_has_debug Boolean
    compute='_compute_user_has_debug'
Public methods (1)
  • default_get(self, fields_list)
    @api.model

New fields (0)

No new fields.

Public methods (1)
  • write(self, vals)

New fields (0)

No new fields.

Public methods (0)

No public methods.