@ -0,0 +1,57 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Raneesha M K (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 odoo import fields, models |
|||
|
|||
|
|||
class ProductTemplate(models.Model): |
|||
"""Inheriting product template model for adding the field price_call into |
|||
the combination_info""" |
|||
_inherit = 'product.template' |
|||
|
|||
def _get_combination_info(self, combination=False, product_id=False, |
|||
add_qty=1, pricelist=False, |
|||
parent_combination=False, |
|||
only_template=False): |
|||
# Call the parent method to get the initial combination_info |
|||
combination_info = super(ProductTemplate, |
|||
self)._get_combination_info( |
|||
combination=combination, product_id=product_id, |
|||
add_qty=add_qty, pricelist=pricelist, |
|||
parent_combination=parent_combination, |
|||
only_template=only_template) |
|||
|
|||
if combination_info.get('product_id'): |
|||
product = self.env['product.product'].browse( |
|||
combination_info['product_id']) |
|||
combination_info['price_call'] = product.price_call |
|||
return combination_info |
|||
|
|||
|
|||
class ProductProduct(models.Model): |
|||
"""Inheriting product variants model for adding a field that will hide |
|||
price from website""" |
|||
_inherit = 'product.product' |
|||
|
|||
price_call = fields.Boolean(string="Call for Price", |
|||
help="This will hide the price and cart button" |
|||
"from shop and customer can request by " |
|||
"calling for price") |
@ -1,32 +0,0 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Raneesha M K (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 odoo import fields, models |
|||
|
|||
|
|||
class ProductTemplate(models.Model): |
|||
"""Inheriting product variants model for adding a field |
|||
that will hide price from website""" |
|||
_inherit = 'product.template' |
|||
|
|||
price_call = fields.Boolean(string="Call for Price", |
|||
help="This will hide the price and cart button from shop " |
|||
"and customer can request by calling for price") |
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 388 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 307 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 274 KiB |
Before Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 298 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 278 KiB |
@ -1,26 +1,122 @@ |
|||
/** |
|||
* This file is used to give a success alert after requesting a call for price. |
|||
*/ |
|||
|
|||
odoo.define('call_for_price_website.create', function (require) { |
|||
odoo.define('call_for_price_website.create_call_form', function(require) { |
|||
"use strict"; |
|||
const rpc = require('web.rpc'); |
|||
var core = require('web.core'); |
|||
var Dialog = require('web.Dialog'); |
|||
var publicWidget = require('web.public.widget'); |
|||
|
|||
$('#send_btn').on('click', function(){ |
|||
var first = $('#first_name').val(); |
|||
var last = $('#last_name').val(); |
|||
var product_id = $('#product_id').val(); |
|||
var phone = $('#phone').val(); |
|||
var email = $('#email').val(); |
|||
var message = $('#message').val(); |
|||
var qty = $('#quantity').val(); |
|||
publicWidget.registry.CallForPrice = publicWidget.Widget.extend({ |
|||
selector: '.oe_website_sale', |
|||
events: { |
|||
'click #send_btn': 'callForPrice', |
|||
'click #button_call_for_price': 'modalShow', |
|||
'click #call_modal_close': 'modalHide' |
|||
}, |
|||
callForPrice: function() { |
|||
var self = this; |
|||
var first = self.$el.find('#first_name').val(); |
|||
var last = self.$el.find('#last_name').val(); |
|||
var product_id = self.$el.find('#product_id').val(); |
|||
var phone = self.$el.find('#phone').val(); |
|||
var email = self.$el.find('#email').val(); |
|||
var message = self.$el.find('#message').val(); |
|||
var qty = self.$el.find('#quantity').val(); |
|||
/** |
|||
* Validate email address format using a regular expression. |
|||
* email - The email address to validate. |
|||
* returns - True if the email is valid, false otherwise. |
|||
*/ |
|||
function validateEmail(email) { |
|||
// Email validation regex pattern
|
|||
var emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; |
|||
return emailPattern.test(email); |
|||
} |
|||
/** |
|||
* Validate phone number format using a regular expression. |
|||
* phone - The phone number to validate. |
|||
* returns - True if the phone number is valid, false otherwise. |
|||
*/ |
|||
function validatePhoneNumber(phone) { |
|||
// Phone number validation regex pattern (without alphabets)
|
|||
var phonePattern = /^[^A-Za-z]*$/ |
|||
return phonePattern.test(phone); |
|||
} |
|||
if (first && phone) { |
|||
if (!$.isNumeric(qty)) { |
|||
var modal = new Dialog(null, { |
|||
title: "Warning", |
|||
$content: $('<div>').text("Quantity should be a numeric value."), |
|||
buttons: [{ |
|||
text: "Close", |
|||
close: true |
|||
}], |
|||
}); |
|||
modal.open(); |
|||
return; |
|||
} |
|||
if (!validateEmail(email)) { |
|||
var modal = new Dialog(null, { |
|||
title: "Warning", |
|||
$content: $('<div>').text("Please enter a valid email address."), |
|||
buttons: [{ |
|||
text: "Close", |
|||
close: true |
|||
}], |
|||
}); |
|||
modal.open(); |
|||
return; |
|||
} |
|||
if (!validatePhoneNumber(phone)) { |
|||
var modal = new Dialog(null, { |
|||
title: "Warning", |
|||
$content: $('<div>').text("Please enter a valid phone number."), |
|||
buttons: [{ |
|||
text: "Close", |
|||
close: true |
|||
}], |
|||
}); |
|||
modal.open(); |
|||
return; |
|||
} |
|||
rpc.query({ |
|||
model: "call.price", |
|||
method: "create_form", |
|||
args: [first, last, product_id, phone, email, message, qty] |
|||
}).then(function(result) { |
|||
document.getElementById('alert_message').style.display = "block" |
|||
self.$el.find('#alert_message')[0].style.display = "block" |
|||
self.$el.find('#call_for_price')[0].style.display = 'none'; |
|||
}); |
|||
} else { |
|||
var modal = new Dialog(null, { |
|||
title: "Warning", |
|||
$content: $('<div>').text("Please enter the required information."), |
|||
buttons: [{ |
|||
text: "Close", |
|||
close: true |
|||
}], |
|||
}); |
|||
modal.open(); |
|||
} |
|||
}, |
|||
modalShow: function() { |
|||
this.resetFormFields(); |
|||
this.$el.find('#call_for_price')[0].style.display = 'block'; |
|||
}, |
|||
modalHide: function() { |
|||
this.$el.find('#call_for_price')[0].style.display = 'none'; |
|||
}, |
|||
resetFormFields: function() { |
|||
this.$el.find('#first_name').val(''); |
|||
this.$el.find('#last_name').val(''); |
|||
this.$el.find('#email').val(''); |
|||
this.$el.find('#phone').val(''); |
|||
this.$el.find('#quantity').val(''); |
|||
this.$el.find('#message').val(''); |
|||
}, |
|||
|
|||
}); |
|||
return publicWidget.registry.CallForPrice; |
|||
}); |
@ -0,0 +1,69 @@ |
|||
/** |
|||
* CustomVariantMixin module for Odoo. |
|||
* This module extends the VariantMixin functionality from website_sale to handle custom behavior. |
|||
*/ |
|||
odoo.define('call_for_price_website.CustomVariantMixin', function(require) { |
|||
'use strict'; |
|||
|
|||
// Import the VariantMixin from website_sale module
|
|||
var VariantMixin = require('website_sale.VariantMixin'); |
|||
// Store a reference to the original onChangeCombination function
|
|||
const originalOnChangeCombination = VariantMixin._onChangeCombination; |
|||
// Override the onChangeCombination function to implement custom behavior
|
|||
VariantMixin._onChangeCombination = function(ev, $parent, combination) { |
|||
const $pricePerUom = $parent.find(".o_base_unit_price:first .oe_currency_value"); |
|||
if ($pricePerUom) { |
|||
if (combination.is_combination_possible !== false && combination.base_unit_price != 0) { |
|||
$pricePerUom.parents(".o_base_unit_price_wrapper").removeClass("d-none"); |
|||
$pricePerUom.text(this._priceToStr(combination.base_unit_price)); |
|||
$parent.find(".oe_custom_base_unit:first").text(combination.base_unit_name); |
|||
} else { |
|||
$pricePerUom.parents(".o_base_unit_price_wrapper").addClass("d-none"); |
|||
} |
|||
} |
|||
// Triggers a new JS event with the correct payload, which is then handled
|
|||
// by the google analytics tracking code.
|
|||
// Indeed, every time another variant is selected, a new view_item event
|
|||
// needs to be tracked by google analytics.
|
|||
if ('product_tracking_info' in combination) { |
|||
const $product = $('#product_detail'); |
|||
$product.data('product-tracking-info', combination['product_tracking_info']); |
|||
$product.trigger('view_item_event', combination['product_tracking_info']); |
|||
} |
|||
const addToCart = $parent.find('#add_to_cart_wrap'); |
|||
const contactUsButton = $parent.find('#contact_us_wrapper'); |
|||
const productPrice = $parent.find('.product_price'); |
|||
const quantity = $parent.find('.css_quantity'); |
|||
const product_unavailable = $parent.find('#product_unavailable'); |
|||
const price_call_div = $parent.find('#price_call_hide'); |
|||
|
|||
if (combination.prevent_zero_price_sale) { |
|||
productPrice.removeClass('d-inline-block').addClass('d-none'); |
|||
quantity.removeClass('d-inline-flex').addClass('d-none'); |
|||
addToCart.removeClass('d-inline-flex').addClass('d-none'); |
|||
contactUsButton.removeClass('d-none').addClass('d-flex'); |
|||
product_unavailable.removeClass('d-none').addClass('d-flex') |
|||
} else if (combination.price_call) { |
|||
productPrice.removeClass('d-inline-block').addClass('d-none'); |
|||
quantity.removeClass('d-inline-flex').addClass('d-none'); |
|||
addToCart.removeClass('d-inline-flex').addClass('d-none'); |
|||
contactUsButton.removeClass('d-none').addClass('d-flex'); |
|||
price_call_div.removeClass('d-none').addClass('d-flex'); |
|||
this.$el.find('#add_to_cart')[0].style.display = "none"; |
|||
this.$el.find('#price_of_product')[0].style.display = "none"; |
|||
this.$el.find('#price_of_product')[0].style.display = "none"; |
|||
} else { |
|||
productPrice.removeClass('d-none').addClass('d-inline-block'); |
|||
quantity.removeClass('d-none').addClass('d-inline-flex'); |
|||
addToCart.removeClass('d-none').addClass('d-inline-flex'); |
|||
contactUsButton.removeClass('d-flex').addClass('d-none'); |
|||
product_unavailable.removeClass('d-flex').addClass('d-none') |
|||
price_call_div.removeClass('d-flex').addClass('d-none') |
|||
this.$el.find('#add_to_cart')[0].style.display = "block"; |
|||
this.$el.find('#price_of_product')[0].style.display = "block"; |
|||
this.$el.find('#price_of_product')[0].style.display = "block"; |
|||
} |
|||
// Call the original onChangeCombination function
|
|||
originalOnChangeCombination.apply(this, [ev, $parent, combination]); |
|||
}; |
|||
}); |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Inheriting product variant view form to add the 'call for price' field --> |
|||
<record id="product_normal_form_view" model="ir.ui.view"> |
|||
<field name="name"> |
|||
product.product.view.form.inherit.call.for.price.website |
|||
</field> |
|||
<field name="model">product.product</field> |
|||
<field name="inherit_id" ref="product.product_normal_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='public_categ_ids']" position="after"> |
|||
<field name="price_call"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -1,14 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!--This file is used to add a field on product variants for hiding price--> |
|||
<record id="product_template_view_form" model="ir.ui.view"> |
|||
<field name="name">product.template.view.form.inherit.call.for.price.website</field> |
|||
<field name="model">product.template</field> |
|||
<field name="inherit_id" ref="website_sale.product_template_only_website_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='public_categ_ids']" position="after"> |
|||
<field name="price_call"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |