19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import loyalty_program
from . import loyalty_reward
from . import sale_order

View file

@ -0,0 +1,35 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, models
class LoyaltyProgram(models.Model):
_inherit = 'loyalty.program'
@api.model
def _program_type_default_values(self):
res = super()._program_type_default_values()
# Add a loyalty reward for free shipping
if 'loyalty' in res:
res['loyalty']['reward_ids'].append((0, 0, {
'reward_type': 'shipping',
'required_points': 100,
}))
return res
@api.model
def get_program_templates(self):
# Override 'promotion' template to say free shipping
res = super().get_program_templates()
if 'promotion' in res:
res['promotion']['description'] = _("Automatic promotion: free shipping on orders higher than $50")
return res
@api.model
def _get_template_values(self):
res = super()._get_template_values()
if 'promotion' in res:
res['promotion']['reward_ids'] = [(5, 0, 0), (0, 0, {
'reward_type': 'shipping',
})]
return res

View file

@ -0,0 +1,23 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, fields, models
class LoyaltyReward(models.Model):
_inherit = 'loyalty.reward'
reward_type = fields.Selection(
selection_add=[('shipping', 'Free Shipping')],
ondelete={'shipping': 'set default'})
def _compute_description(self):
shipping_rewards = self.filtered(lambda r: r.reward_type == 'shipping')
super(LoyaltyReward, self - shipping_rewards)._compute_description()
shipping_rewards.description = _('Free shipping')
for reward in shipping_rewards:
if reward.discount_max_amount:
format_string = '%(amount)g %(symbol)s'
if reward.currency_id.position == 'before':
format_string = '%(symbol)s %(amount)g'
formatted_amount = format_string % {'amount': reward.discount_max_amount, 'symbol': reward.currency_id.symbol}
reward.description += _(' (Max %s)', formatted_amount)

View file

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, models
from odoo.fields import Command
class SaleOrder(models.Model):
_inherit = 'sale.order'
def _get_no_effect_on_threshold_lines(self):
self.ensure_one()
lines = self.order_line.filtered(lambda line:\
line.is_delivery or\
line.reward_id.reward_type == 'shipping')
return lines + super()._get_no_effect_on_threshold_lines()
# delivery overrides
def _get_lines_impacting_invoice_status(self):
return super()._get_lines_impacting_invoice_status().filtered(
lambda line: not line.is_reward_line
def _compute_amount_total_without_delivery(self):
res = super()._compute_amount_total_without_delivery()
return res - sum(
self.order_line.filtered(
lambda l: l.coupon_id and l.coupon_id.program_type in ['ewallet', 'gift_card']
).mapped('price_unit')
)
# sale_loyalty overrides
def _get_no_effect_on_threshold_lines(self):
res = super()._get_no_effect_on_threshold_lines()
return res + self.order_line.filtered(
lambda line: line.is_delivery or line.reward_id.reward_type == 'shipping')
def _get_not_rewarded_order_lines(self):
"""Exclude delivery lines from consideration for reward points."""
order_line = super()._get_not_rewarded_order_lines()
return order_line.filtered(lambda line: not line.is_delivery)
def _get_reward_values_free_shipping(self, reward, coupon, **kwargs):
delivery_line = self.order_line.filtered(lambda l: l.is_delivery)
taxes = delivery_line.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id)
delivery_line = self.order_line.filtered(lambda l: l.is_delivery)[:1]
taxes = delivery_line.product_id.taxes_id._filter_taxes_by_company(self.company_id)
taxes = self.fiscal_position_id.map_tax(taxes)
max_discount = reward.discount_max_amount or float('inf')
return [{
@ -37,11 +42,10 @@ class SaleOrder(models.Model):
'product_id': reward.discount_line_product_id.id,
'price_unit': -min(max_discount, delivery_line.price_unit or 0),
'product_uom_qty': 1,
'product_uom': reward.discount_line_product_id.uom_id.id,
'order_id': self.id,
'is_reward_line': True,
'sequence': max(self.order_line.filtered(lambda x: not x.is_reward_line).mapped('sequence'), default=0) + 1,
'tax_id': [(Command.CLEAR, 0, 0)] + [(Command.LINK, tax.id, False) for tax in taxes],
'tax_ids': [Command.clear()] + [Command.link(tax.id) for tax in taxes],
}]
def _get_reward_line_values(self, reward, coupon, **kwargs):