mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 18:52:07 +02:00
19.0 vanilla
This commit is contained in:
parent
79f83631d5
commit
73afc09215
6267 changed files with 1534193 additions and 1130106 deletions
166
odoo-bringout-oca-ocb-sale/sale/wizard/sale_order_discount.py
Normal file
166
odoo-bringout-oca-ocb-sale/sale/wizard/sale_order_discount.py
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.fields import Command
|
||||
from odoo.tools import float_repr
|
||||
|
||||
|
||||
class SaleOrderDiscount(models.TransientModel):
|
||||
_name = 'sale.order.discount'
|
||||
_description = "Discount Wizard"
|
||||
|
||||
sale_order_id = fields.Many2one(
|
||||
'sale.order', default=lambda self: self.env.context.get('active_id'), required=True)
|
||||
company_id = fields.Many2one(related='sale_order_id.company_id')
|
||||
currency_id = fields.Many2one(related='sale_order_id.currency_id')
|
||||
discount_amount = fields.Monetary(string="Amount")
|
||||
discount_percentage = fields.Float(string="Percentage")
|
||||
discount_type = fields.Selection(
|
||||
selection=[
|
||||
('sol_discount', "On All Order Lines"),
|
||||
('so_discount', "Global Discount"),
|
||||
('amount', "Fixed Amount"),
|
||||
],
|
||||
default='sol_discount',
|
||||
)
|
||||
|
||||
# CONSTRAINT METHODS #
|
||||
|
||||
@api.constrains('discount_type', 'discount_percentage')
|
||||
def _check_discount_amount(self):
|
||||
for wizard in self:
|
||||
if (
|
||||
wizard.discount_type in ('sol_discount', 'so_discount')
|
||||
and wizard.discount_percentage > 1.0
|
||||
):
|
||||
raise ValidationError(_("Invalid discount amount"))
|
||||
|
||||
def _prepare_discount_product_values(self):
|
||||
self.ensure_one()
|
||||
values = {
|
||||
'name': _('Discount'),
|
||||
'type': 'service',
|
||||
'invoice_policy': 'order',
|
||||
'list_price': 0.0,
|
||||
'company_id': self.company_id.id,
|
||||
'taxes_id': None,
|
||||
}
|
||||
services_category = self.env.ref('product.product_category_services', raise_if_not_found=False)
|
||||
if services_category:
|
||||
values['categ_id'] = services_category.id
|
||||
return values
|
||||
|
||||
def _prepare_global_discount_so_lines(self, base_lines):
|
||||
self.ensure_one()
|
||||
AccountTax = self.env['account.tax']
|
||||
discount_dp = self.env['decimal.precision'].precision_get('Discount')
|
||||
has_multiple_tax_combinations = len(set(base_line['tax_ids'] for base_line in base_lines if base_line['tax_ids'])) > 1
|
||||
so_line_values_list = []
|
||||
for base_line in base_lines:
|
||||
|
||||
# The name of the so line.
|
||||
if has_multiple_tax_combinations:
|
||||
if self.discount_type == 'so_discount':
|
||||
so_line_description = self.env._(
|
||||
"Discount %(percent)s%%"
|
||||
"- On products with the following taxes %(taxes)s",
|
||||
percent=float_repr(self.discount_percentage * 100.0, discount_dp),
|
||||
taxes=", ".join(base_line['tax_ids'].mapped('name')),
|
||||
)
|
||||
else:
|
||||
so_line_description = self.env._(
|
||||
"Discount"
|
||||
"- On products with the following taxes %(taxes)s",
|
||||
taxes=", ".join(base_line['tax_ids'].mapped('name')),
|
||||
)
|
||||
else:
|
||||
if self.discount_type == 'so_discount':
|
||||
so_line_description = self.env._(
|
||||
"Discount %(percent)s%%",
|
||||
percent=float_repr(self.discount_percentage * 100.0, discount_dp),
|
||||
)
|
||||
else:
|
||||
so_line_description = self.env._("Discount")
|
||||
|
||||
so_line_values_list.append({
|
||||
'name': so_line_description,
|
||||
'product_id': base_line['product_id'].id,
|
||||
'price_unit': base_line['price_unit'],
|
||||
'technical_price_unit': 0,
|
||||
'product_uom_qty': base_line['quantity'],
|
||||
'tax_ids': [Command.set(base_line['tax_ids'].ids)],
|
||||
'extra_tax_data': AccountTax._export_base_line_extra_tax_data(base_line),
|
||||
'sequence': 999,
|
||||
})
|
||||
|
||||
return so_line_values_list
|
||||
|
||||
def _get_discount_product(self):
|
||||
"""Return product.product used for discount line"""
|
||||
self.ensure_one()
|
||||
company = self.company_id
|
||||
discount_product = company.sale_discount_product_id
|
||||
if not discount_product:
|
||||
if (
|
||||
self.env['product.product'].has_access('create')
|
||||
and company.has_access('write')
|
||||
and company._has_field_access(company._fields['sale_discount_product_id'], 'write')
|
||||
):
|
||||
company.sale_discount_product_id = self.env['product.product'].create(
|
||||
self._prepare_discount_product_values()
|
||||
)
|
||||
else:
|
||||
raise ValidationError(_(
|
||||
"There does not seem to be any discount product configured for this company yet."
|
||||
" You can either use a per-line discount, or ask an administrator to grant the"
|
||||
" discount the first time."
|
||||
))
|
||||
discount_product = company.sale_discount_product_id
|
||||
return discount_product
|
||||
|
||||
def _create_discount_lines(self):
|
||||
self.ensure_one()
|
||||
self = self.with_context(lang=self.sale_order_id._get_lang())
|
||||
|
||||
discount_product = self._get_discount_product()
|
||||
|
||||
if self.discount_type == 'so_discount':
|
||||
amount_type = 'percent'
|
||||
amount = self.discount_percentage * 100.0
|
||||
else: # self.discount_type == 'amount':
|
||||
amount_type = 'fixed'
|
||||
amount = self.discount_amount
|
||||
|
||||
order = self.sale_order_id
|
||||
AccountTax = self.env['account.tax']
|
||||
order_lines = order.order_line.filtered(lambda x: not x.display_type)
|
||||
base_lines = [line._prepare_base_line_for_taxes_computation() for line in order_lines]
|
||||
AccountTax._add_tax_details_in_base_lines(base_lines, order.company_id)
|
||||
AccountTax._round_base_lines_tax_details(base_lines, order.company_id)
|
||||
|
||||
def grouping_function(base_line):
|
||||
return {'product_id': discount_product}
|
||||
|
||||
global_discount_base_lines = AccountTax._prepare_global_discount_lines(
|
||||
base_lines=base_lines,
|
||||
company=self.company_id,
|
||||
amount_type=amount_type,
|
||||
amount=amount,
|
||||
computation_key=f'global_discount,{self.id}',
|
||||
grouping_function=grouping_function,
|
||||
)
|
||||
order.order_line = [
|
||||
Command.create(values)
|
||||
for values in self._prepare_global_discount_so_lines(global_discount_base_lines)
|
||||
]
|
||||
|
||||
def action_apply_discount(self):
|
||||
self.ensure_one()
|
||||
self = self.with_company(self.company_id)
|
||||
if self.discount_type == 'sol_discount':
|
||||
self.sale_order_id.order_line.write({'discount': self.discount_percentage * 100})
|
||||
else:
|
||||
self._create_discount_lines()
|
||||
Loading…
Add table
Add a link
Reference in a new issue