You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
10 KiB
207 lines
10 KiB
# -*- coding: utf-8 -*-
|
|
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
|
|
# Author: Raveena V (odoo@cybrosys.com)
|
|
#
|
|
# You can modify it under the terms of the GNU AFFERO
|
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
# (AGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
from datetime import datetime
|
|
from odoo import fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class SaleOrderLine(models.Model):
|
|
"""Inherits Sale order line to add the functions for checking the
|
|
visibility of the pricelists in order lines and also apply the
|
|
pricelist to order lines"""
|
|
_inherit = 'sale.order.line'
|
|
|
|
pricelist_visibility = fields.Boolean(
|
|
compute="_compute_pricelist_visibility", string="Pricelist Visible",
|
|
help="Multi Pricelist enabled or not")
|
|
applied_pricelist_id = fields.Many2one('product.pricelist',
|
|
string="PriceList",
|
|
help="Price lists that is applied to"
|
|
"the order line.")
|
|
|
|
def _get_display_price(self, product):
|
|
"""Overwrite the function to set the unit price according to the
|
|
applied pricelist from the orderline and the UoM"""
|
|
# TO DO: move me in master/saas-16 on sale.order
|
|
# awa: don't know if it's still the case since we need the
|
|
# "product_no_variant_attribute_value_ids" field now
|
|
# to be able to compute the full price
|
|
# it is possible that a no_variant attribute is still in a variant if
|
|
# the type of the attribute has been changed after creation.
|
|
no_variant_attributes_price_extra = [
|
|
ptav.price_extra for ptav in
|
|
self.product_no_variant_attribute_value_ids.filtered(
|
|
lambda ptav:
|
|
ptav.price_extra and
|
|
ptav not in product.product_template_attribute_value_ids
|
|
)
|
|
]
|
|
if no_variant_attributes_price_extra:
|
|
product = product.with_context(
|
|
no_variant_attributes_price_extra=tuple(
|
|
no_variant_attributes_price_extra)
|
|
)
|
|
if self.order_id.pricelist_id.discount_policy == 'with_discount':
|
|
if self.applied_pricelist_id:
|
|
return product.with_context(
|
|
pricelist=self.applied_pricelist_id.id, uom=self.product_uom.id,
|
|
quantity=self.product_uom_qty
|
|
).price
|
|
else:
|
|
return product.with_context(
|
|
pricelist=self.order_id.pricelist_id.id,
|
|
uom=self.product_uom.id).price
|
|
product_context = dict(self.env.context,
|
|
partner_id=self.order_id.partner_id.id,
|
|
date=self.order_id.date_order,
|
|
uom=self.product_uom.id)
|
|
final_price, rule_id = self.order_id.pricelist_id.with_context(
|
|
product_context).get_product_price_rule(product or self.product_id,
|
|
self.product_uom_qty or 1.0,
|
|
self.order_id.partner_id)
|
|
base_price, currency = self.with_context(
|
|
product_context)._get_real_price_currency(product, rule_id,
|
|
self.product_uom_qty,
|
|
self.product_uom,
|
|
self.order_id.pricelist_id.id)
|
|
if currency != self.order_id.pricelist_id.currency_id:
|
|
base_price = currency._convert(
|
|
base_price, self.order_id.pricelist_id.currency_id,
|
|
self.order_id.company_id or self.env.company,
|
|
self.order_id.date_order or fields.Date.today())
|
|
# negative discounts (= surcharge) are included in the display price
|
|
return max(base_price, final_price)
|
|
|
|
def apply_pricelist(self):
|
|
"""This function will help to select all the pricelists
|
|
for a product in order line and apply it"""
|
|
for rec in self:
|
|
date_time_today = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
|
|
# find the matching price list for a product
|
|
price_ids = self.env['product.pricelist.item'].search(
|
|
['|', '|', ('product_tmpl_id', '=', False),
|
|
('categ_id', '=', rec.product_id.categ_id.id),
|
|
('product_tmpl_id', '=', rec.product_id.product_tmpl_id.id),
|
|
('min_quantity', '<=', rec.product_uom_qty),'|',
|
|
('date_start', '<=', date_time_today),
|
|
('date_start', '=', False), '|',
|
|
('date_end', '>=', date_time_today),
|
|
('date_end', '=', False),
|
|
])
|
|
variant_ids = self.env['product.pricelist.item'].search(
|
|
[
|
|
('product_id', '=', rec.product_id.id),
|
|
('min_quantity', '<=', rec.product_uom_qty),
|
|
'|', ('date_start', '<=', date_time_today),
|
|
('date_start', '=', False), '|',
|
|
('date_end', '>=', date_time_today),
|
|
('date_end', '=', False),
|
|
])
|
|
combined_ids = price_ids + variant_ids
|
|
if combined_ids:
|
|
pricelist_wizard = self.env['pricelist.wizard'].create({
|
|
'order_line_id': rec.id,
|
|
'line_ids': [(0, 0, {
|
|
'pricelist_id': price.pricelist_id.id,
|
|
'product_id': rec.product_id.id,
|
|
'unit_price': self.unit_price(price),
|
|
'unit_cost': rec.product_id.standard_price,
|
|
'uom_id': rec.product_id.uom_id.id
|
|
}) for price in combined_ids],
|
|
})
|
|
else:
|
|
raise UserError(_(
|
|
"No price list is configured for this product!"))
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'new',
|
|
'name': 'Select Pricelist',
|
|
'view_mode': 'form',
|
|
'view_id': self.env.ref(
|
|
"multi_pricelist.pricelist_wizard_view_form", False).id,
|
|
'res_model': 'pricelist.wizard',
|
|
'res_id': pricelist_wizard.id,
|
|
}
|
|
|
|
def _compute_pricelist_visibility(self):
|
|
""" Computes pricelist_visibility by checking the config parameter."""
|
|
for rec in self:
|
|
rec.pricelist_visibility = self.env[
|
|
'ir.config_parameter'].sudo().get_param(
|
|
'multi_pricelist.multi_pricelist')
|
|
if rec.order_id.state in ['sale', 'done', 'cancel']:
|
|
rec.pricelist_visibility = False
|
|
|
|
def unit_price(self, price):
|
|
"""Compute the unit price of the product according to the
|
|
price_list_item"""
|
|
if price.compute_price == 'fixed':
|
|
unt_price = price.fixed_price
|
|
elif price.compute_price == 'percentage' and price.percent_price != 0:
|
|
unt_price = self.product_id.list_price * (
|
|
1 - price.percent_price / 100)
|
|
elif price.compute_price == 'formula' and price.base == 'list_price':
|
|
unt_price = (self.product_id.list_price * (
|
|
1 - price.price_discount / 100) + price.price_surcharge)
|
|
if price.price_min_margin or price.price_max_margin:
|
|
if (unt_price < price.price_min_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_min_margin +
|
|
self.product_id.list_price)
|
|
elif (unt_price > price.price_max_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_max_margin +
|
|
self.product_id.list_price)
|
|
else:
|
|
unt_price = unt_price
|
|
elif price.compute_price == 'formula' and price.base == 'standard_price':
|
|
unt_price = (self.product_id.standard_price * (
|
|
1 - price.price_discount / 100) + price.price_surcharge)
|
|
if price.price_min_margin or price.price_max_margin:
|
|
if (unt_price < price.price_min_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_min_margin +
|
|
self.product_id.list_price)
|
|
elif (unt_price > price.price_max_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_max_margin +
|
|
self.product_id.list_price)
|
|
else:
|
|
unt_price = unt_price
|
|
elif price.compute_price == 'formula' and price.base == 'pricelist':
|
|
unt_price = (self.unit_price(price.base_pricelist_id.item_ids) * (
|
|
1 - price.price_discount / 100) + price.price_surcharge)
|
|
if price.price_min_margin or price.price_max_margin:
|
|
if (unt_price < price.price_min_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_min_margin +
|
|
self.product_id.list_price)
|
|
elif (unt_price > price.price_max_margin +
|
|
self.product_id.list_price):
|
|
unt_price = (price.price_max_margin +
|
|
self.product_id.list_price)
|
|
else:
|
|
unt_price = unt_price
|
|
else:
|
|
unt_price = self.product_id.list_price
|
|
return unt_price
|
|
|