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))}
 | |
| 
 |