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.
		
		
		
		
		
			
		
			
				
					
					
						
							211 lines
						
					
					
						
							9.9 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							211 lines
						
					
					
						
							9.9 KiB
						
					
					
				
								# -*- coding: utf-8 -*-
							 | 
						|
								#############################################################################
							 | 
						|
								#
							 | 
						|
								#    Cybrosys Technologies Pvt. Ltd.
							 | 
						|
								#
							 | 
						|
								#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
							 | 
						|
								#    Author: Fathima Mazlin AM @ cybrosys,(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/>.
							 | 
						|
								#
							 | 
						|
								#############################################################################
							 | 
						|
								import logging
							 | 
						|
								from odoo import api, fields, models, _
							 | 
						|
								from odoo.http import request
							 | 
						|
								from odoo.exceptions import UserError, ValidationError
							 | 
						|
								_logger = logging.getLogger(__name__)
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class SaleOrder(models.Model):
							 | 
						|
								    """ Inherit the 'sale.order' model to overwrite the _compute_cart_info
							 | 
						|
								    and _cart_update functions."""
							 | 
						|
								    _inherit = 'sale.order'
							 | 
						|
								
							 | 
						|
								    cart_quantity = fields.Float(compute='_compute_cart_info',
							 | 
						|
								                                 string='Cart Quantity', help="Cart Quantity "
							 | 
						|
								                                                              "in eCommerce")
							 | 
						|
								
							 | 
						|
								    @api.depends('order_line.product_uom_qty', 'order_line.product_id')
							 | 
						|
								    def _compute_cart_info(self):
							 | 
						|
								        """Making cart_quantity integer is avoided in order
							 | 
						|
								        to represent it in decimal values"""
							 | 
						|
								        for order in self:
							 | 
						|
								            order.cart_quantity = float(sum(order.mapped
							 | 
						|
								                                            ('website_order_line'
							 | 
						|
								                                             '.product_uom_qty')))
							 | 
						|
								            order.only_services = all(line.product_id.type == 'service'
							 | 
						|
								                                      for line in order.website_order_line)
							 | 
						|
								
							 | 
						|
								    def _cart_update(self, product_id, line_id=None, add_qty=0, set_qty=0,
							 | 
						|
								                     **kwargs):
							 | 
						|
								        """ Add or set product quantity, add_qty can be negative.
							 | 
						|
								         Making add_qty and set_qty integer are avoided in order
							 | 
						|
								         to represent them as decimal values."""
							 | 
						|
								        self.ensure_one()
							 | 
						|
								        product_context = dict(self.env.context)
							 | 
						|
								        product_context.setdefault('lang', self.sudo().partner_id.lang)
							 | 
						|
								        SaleOrderLineSudo = self.env['sale.order.line'].sudo().with_context(
							 | 
						|
								            product_context)
							 | 
						|
								        # Change lang to get correct name of attributes/values
							 | 
						|
								        product_with_context = self.env['product.product'].with_context(
							 | 
						|
								            product_context)
							 | 
						|
								        product = product_with_context.browse(int(product_id)).exists()
							 | 
						|
								        if not product or (
							 | 
						|
								                not line_id and not product._is_add_to_cart_allowed()):
							 | 
						|
								            raise UserError(
							 | 
						|
								                _("The given product does not exist therefore it cannot "
							 | 
						|
								                  "be added to cart."))
							 | 
						|
								        try:
							 | 
						|
								            if add_qty:
							 | 
						|
								                add_qty = float(add_qty)
							 | 
						|
								        except ValueError:
							 | 
						|
								            add_qty = 1
							 | 
						|
								        try:
							 | 
						|
								            if set_qty:
							 | 
						|
								                set_qty = float(set_qty)
							 | 
						|
								        except ValueError:
							 | 
						|
								            set_qty = 0
							 | 
						|
								        quantity = 0
							 | 
						|
								        order_line = False
							 | 
						|
								        if self.state != 'draft':
							 | 
						|
								            request.session['sale_order_id'] = None
							 | 
						|
								            raise UserError(
							 | 
						|
								                _('It is forbidden to modify a sales order which is not in '
							 | 
						|
								                  'draft status.'))
							 | 
						|
								        if line_id is not False:
							 | 
						|
								            order_line = self._cart_find_product_line(product_id, line_id,
							 | 
						|
								                                                      **kwargs)[:1]
							 | 
						|
								        # Create line if no line with product_id can be located
							 | 
						|
								        if not order_line:
							 | 
						|
								            no_variant_attribute_values = kwargs.get(
							 | 
						|
								                'no_variant_attribute_values') or []
							 | 
						|
								            received_no_variant_values = product.env[
							 | 
						|
								                'product.template.attribute.value'].browse(
							 | 
						|
								                [int(ptav['value']) for ptav in no_variant_attribute_values])
							 | 
						|
								            received_combination = \
							 | 
						|
								                product.product_template_attribute_value_ids\
							 | 
						|
								                | received_no_variant_values
							 | 
						|
								            product_template = product.product_tmpl_id
							 | 
						|
								            # Handle all cases where incorrect or incomplete data are received
							 | 
						|
								            combination = product_template._get_closest_possible_combination(
							 | 
						|
								                received_combination)
							 | 
						|
								            # Get or create (if dynamic) the correct variant
							 | 
						|
								            product = product_template._create_product_variant(combination)
							 | 
						|
								            if not product:
							 | 
						|
								                raise UserError(
							 | 
						|
								                    _("The given combination does not exist therefore it "
							 | 
						|
								                      "cannot be added to cart."))
							 | 
						|
								            product_id = product.id
							 | 
						|
								            values = self._website_product_id_change(self.id, product_id,
							 | 
						|
								                                                     qty=1, **kwargs)
							 | 
						|
								            # Add no_variant attributes that were not received
							 | 
						|
								            for ptav in combination.filtered(
							 | 
						|
								                    lambda ptav:
							 | 
						|
								                    ptav.attribute_id.create_variant ==
							 | 
						|
								                    'no_variant' and ptav not in received_no_variant_values):
							 | 
						|
								                no_variant_attribute_values.append({
							 | 
						|
								                    'value': ptav.id,
							 | 
						|
								                })
							 | 
						|
								            # Save no_variant attributes values
							 | 
						|
								            if no_variant_attribute_values:
							 | 
						|
								                values['product_no_variant_attribute_value_ids'] = [
							 | 
						|
								                    (6, 0, [int(attribute['value']) for attribute in
							 | 
						|
								                            no_variant_attribute_values])
							 | 
						|
								                ]
							 | 
						|
								            # Add is_custom attribute values that were not received
							 | 
						|
								            custom_values = kwargs.get('product_custom_attribute_values') or []
							 | 
						|
								            received_custom_values = product.env[
							 | 
						|
								                'product.template.attribute.value'].browse(
							 | 
						|
								                [int(ptav['custom_product_template_attribute_value_id']) for
							 | 
						|
								                 ptav in custom_values])
							 | 
						|
								            for ptav in combination.filtered(
							 | 
						|
								                    lambda ptav:
							 | 
						|
								                    ptav.is_custom and ptav not in received_custom_values):
							 | 
						|
								                custom_values.append({
							 | 
						|
								                    'custom_product_template_attribute_value_id': ptav.id,
							 | 
						|
								                    'custom_value': '',
							 | 
						|
								                })
							 | 
						|
								            # Save is_custom attributes values
							 | 
						|
								            if custom_values:
							 | 
						|
								                values['product_custom_attribute_value_ids'] = [(0, 0, {
							 | 
						|
								                    'custom_product_template_attribute_value_id': custom_value[
							 | 
						|
								                        'custom_product_template_attribute_value_id'],
							 | 
						|
								                    'custom_value': custom_value['custom_value']
							 | 
						|
								                }) for custom_value in custom_values]
							 | 
						|
								            # Create the line
							 | 
						|
								            order_line = SaleOrderLineSudo.create(values)
							 | 
						|
								            try:
							 | 
						|
								                order_line._compute_tax_id()
							 | 
						|
								            except ValidationError as e:
							 | 
						|
								                # The validation may occur in backend (eg: taxcloud)
							 | 
						|
								                # but should fail silently in frontend
							 | 
						|
								                _logger.debug(
							 | 
						|
								                    "ValidationError occurs during tax compute. %s" % (e))
							 | 
						|
								            if add_qty:
							 | 
						|
								                add_qty -= 1
							 | 
						|
								        # Compute new quantity
							 | 
						|
								        if set_qty:
							 | 
						|
								            quantity = set_qty
							 | 
						|
								        elif add_qty is not None:
							 | 
						|
								            quantity = order_line.product_uom_qty + (add_qty or 0)
							 | 
						|
								        # Remove zero of negative lines
							 | 
						|
								        if quantity <= 0:
							 | 
						|
								            linked_line = order_line.linked_line_id
							 | 
						|
								            order_line.unlink()
							 | 
						|
								            if linked_line:
							 | 
						|
								                # Update description of the parent
							 | 
						|
								                linked_product = product_with_context.browse(
							 | 
						|
								                    linked_line.product_id.id)
							 | 
						|
								                linked_line.name = \
							 | 
						|
								                    linked_line.get_sale_order_line_multiline_description_sale(
							 | 
						|
								                        linked_product)
							 | 
						|
								        else:
							 | 
						|
								            # Update line
							 | 
						|
								            no_variant_attributes_price_extra = [
							 | 
						|
								                ptav.price_extra for ptav in order_line
							 | 
						|
								                .product_no_variant_attribute_value_ids]
							 | 
						|
								            values = self.with_context(no_variant_attributes_price_extra=tuple(
							 | 
						|
								                no_variant_attributes_price_extra))._website_product_id_change(
							 | 
						|
								                self.id, product_id, qty=quantity, **kwargs)
							 | 
						|
								            order = self.sudo().browse(self.id)
							 | 
						|
								            if self.pricelist_id.discount_policy == 'with_discount' \
							 | 
						|
								                    and not self.env.context.get('fixed_price'):
							 | 
						|
								                product_context.update({
							 | 
						|
								                    'partner': order.partner_id,
							 | 
						|
								                    'quantity': quantity,
							 | 
						|
								                    'date': order.date_order,
							 | 
						|
								                    'pricelist': order.pricelist_id.id,
							 | 
						|
								                })
							 | 
						|
								            product_with_context = self.env['product.product'].with_context(
							 | 
						|
								                product_context).with_company(order.company_id.id)
							 | 
						|
								            product = product_with_context.browse(product_id)
							 | 
						|
								            order_line.write(values)
							 | 
						|
								            # Link a product to the sales order
							 | 
						|
								            if kwargs.get('linked_line_id'):
							 | 
						|
								                linked_line = SaleOrderLineSudo.browse(kwargs['linked_'
							 | 
						|
								                                                              'line_id'])
							 | 
						|
								                order_line.write({
							 | 
						|
								                    'linked_line_id': linked_line.id,
							 | 
						|
								                })
							 | 
						|
								                linked_product = product_with_context.browse(
							 | 
						|
								                    linked_line.product_id.id)
							 | 
						|
								                linked_line.name = \
							 | 
						|
								                    linked_line.get_sale_order_line_multiline_description_sale(
							 | 
						|
								                     linked_product)
							 | 
						|
								            order_line.name = \
							 | 
						|
								                order_line.get_sale_order_line_multiline_description_sale(
							 | 
						|
								                 product)
							 | 
						|
								        option_lines = self.order_line.filtered(
							 | 
						|
								            lambda l: l.linked_line_id.id == order_line.id)
							 | 
						|
								        return {'line_id': order_line.id, 'quantity': quantity,
							 | 
						|
								                'option_ids': list(set(option_lines.ids))}
							 | 
						|
								
							 |