How do I modify PrestaShop 1.5 to display product prices in two currencies at the same time (ie. base currenct and visitor's currency on products listed in product & categories pages):
I think I should be modifying ProductController.php and product.tpl. Is this correct?
Below is one solution for the product page that I find on a forum, but it is for PrestaShop 1.4x:
Override ProductController.php in /controllers/ProductController.php
<?php
class ProductController extends ProductControllerCore{
public function displayContent() {
global $currency;
$second_currency = 'USD';
$productPriceWithTax = Product::getPriceStatic($this->product->id, true, NULL, 6);
if (Product::$_taxCalculationMethod == PS_TAX_INC) {
$productPriceWithTax = Tools::ps_round($productPriceWithTax, 2);
}
$productPriceWithoutEcoTax = (float)($productPriceWithTax - $this->product->ecotax);
$current_currency = $currency->iso_code;
$default_currency = Currency::getDefaultCurrency()->iso_code;
$currency_array = Currency::getCurrencies($object = false, $active = 1);
if ($current_currency == $default_currency) {
foreach ($currency_array as $arr) {
if ((string)$arr['iso_code'] == $second_currency) {
$second_currency_price = Tools::ps_round($productPriceWithoutEcoTax * (float)$arr['conversion_rate'], 2);
}
}
}
self::$smarty->assign('second_currency_price', $second_currency_price . ' ' . $second_currency);
parent::displayContent();
}
}
Modify product.tpl:
{if $priceDisplay >= 0 && $priceDisplay <= 2}
<span id="our_price_display">{convertPrice price=$productPrice}</span>
to
{if $priceDisplay >= 0 && $priceDisplay <= 2}
{$second_currency_price} /
<span id="our_price_display">{convertPrice price=$productPrice}</span>
In above example USD is the second currency ($second_currency='USD'). I was wondering if it would be possible to modify this code for PrestaShop 1.5, which has changed significantly since 1.4x.
You have to loop this array which contains all the currencies you manage: {$currencies}
{foreach from=$currencies item=c}{$c.name}{/foreach}
The default currency is in: {$id_currency_cookie}
If I remember, you have to write this in product.tpl.
I don't know how to display the correct price for your currency. Tell us if you find.
Related
I am setting up a new site in Wix. The page uses an API to fill a simple 4 column table. Sizes, climate, prices, and reserve. I am. trying to figure out how to code a button into column 4 (all rows) that links to the Lightbox "reservation". The reserve button will not be linked to the API, just a form for a customer to fill in.
This is what I currently have. How can I add a button to the last column?
import {getLocationInfo} from 'backend/WssApiService';
import {getLocationReviews} from 'backend/WssApiService';
import {getAvailableLocations} from 'backend/WssApiService';
$w.onReady(function () {
getLocationInfo('xxxxx').then(function(locationInfo) {
//console.log(locationInfo);
$w("#table1").rows = [];
let rows = $w("#table1").rows;
locationInfo.Location.Units.sort((a, b) => (a.Monthly > b.Monthly) ? 1 : -1);
for (var i = 0; i < locationInfo.Location.Units.length; i++) {
var climateControlled = locationInfo.Location.Units[i].SizeDescriptionsField.filter(function(item) {
return item.includes("Climate") && !item.includes("No Climate");
});
//console.log(climateControlled);
if(climateControlled.length > 0)
{
rows.push({Size: locationInfo.Location.Units[i].UnitSize, climate_control : "Yes", Price: '$' + locationInfo.Location.Units[i].Monthly});
}
else
{
rows.push({Size: locationInfo.Location.Units[i].UnitSize, climate_control : "No", Price: '$' + locationInfo.Location.Units[i].Monthly});
}
}
$w("#table1").rows = rows;
You cannot insert a button into a Table in Wix. Use a Repeater for that or add an onCellSelect event handler (https://www.wix.com/corvid/reference/$w.Table.html#onCellSelect) to the table and define the location using code.
This question is based on Get selected variation price in jQuery on Woocommerce Variable products.
I have some code that works on the single product page to display a calculated price based on user input. The problem is that the calculated price also applies to the related products on the bottom of the page. Their price is set to be the same as the product being viewed.
I think the problem lies in the line $('.price').html(total_pris+',-'); where '.price' applies to the related products also. How do I fix this?
My code:
add_action( 'woocommerce_before_add_to_cart_quantity', 'func_option_valgt'
);
function func_option_valgt() {
global $product;
if (has_term('endene','product_cat')){
$variations_data =[]; // Initializing
// Loop through variations data
foreach($product->get_available_variations() as $variation ) {
// Set for each variation ID the corresponding price in the data array (to be used in jQuery)
$variations_data[$variation['variation_id']] = $variation['display_price'];
}
?>
<script>
jQuery(function($) {
var jsonData = <?php echo json_encode($variations_data); ?>,
inputVID = 'input.variation_id';
$('input , #id_dropdown_one_end, #id_dropdown_other_end').change( function(){
if( '' != $(inputVID).val() ) {
var vid = $(inputVID).val(), // VARIATION ID
length = $('#rope_length').val(), // LENGTH
diameter = $('#diameter').val(), // DIAMETER
ene_enden = $('#id_dropdown_one_end').find('option:selected').attr("value_one_end"),
andre_enden = $('#id_dropdown_other_end').find('option:selected').attr("value_other_end"),
vprice = ''; // Initilizing
// Loop through variation IDs / Prices pairs
$.each( jsonData, function( index, price ) {
if( index == $(inputVID).val() ) {
vprice = price; // The right variation price
var ene_enden_conv = Number(ene_enden);
var andre_enden_conv = Number(andre_enden);
var rope_price = (length*vprice) + ene_enden_conv + andre_enden_conv;
var total_pris = rope_price;
if (rope_price != 0){
$('.price').html(total_pris+',-');
}
}
});
}
});
});
</script>
<?php
}
}
To avoid updating related product prices too, you just need to make a little change replacing:
$('.price').html(total_pris+',-');
by:
$('.woocommerce-variation-price > .price').html(total_pris+',-');
This should solve your problem.
I am trying to use Javascript to calculate sum of order in one big form. Each product has its own price, however, there are more prices tied with some products. Each product has it's own price, but if a customer orders bigger quantity of this product, the price will drop to a value that is specified in a database table.
To simplify, the shopping form for one item looks something like this.
<input name="id" value="'.$id.'" type="hidden">
<input name="price_'.$id.'" value="'.$price.'" type="hidden">
<input name="quantity_'.$id.'" type="text" onchange="calculateTotal()">
I have a table with the discounts: itemId, minimumQuantity, priceAfterDiscount. There can be more than one discounts connected with one item. The MySQL query works with LEFT JOIN of Items and Discounts tables.
calculateTotal() calculates the total of order after every input change.
What I would like to do, is to check if the quantity of certain product is greater than the value needed for the discounts and if so, I would like to change the value of the input with price from item's regular price to the discounted one. Then, calculateTotal() will use that price and update the total.
To do so, I think I can do something like adding more hidden inputs with values of all discounts. The function would check if there is a discount linked to every item and if so, it will check if the quantity is greater than requiredQuantity and if this condition is met, it will update the value of price hidden input. Please keep in mind that there can be multiple discounts connected to one item - the function should find the lowest price that meets requiredQuantity.
I am trying to do this - create the hidden inputs and somehow parse them in javascript, but I am just not able to figure this out. I tried my best to explain the problem, however, if my explanation is not sufficient, I will try to answer your questions regarding my issue.
I hope you are able and willing to help me. Thanks for help in advance.
Perhaps something like this example.
CSS
.itemLabel, .currentPrice, .subTotal {
display: inline-block;
width: 40px;
}
#myTotal {
border:2px solid red;
}
HTML
<fieldset id="myInputs"></fieldset>
<div id="myTotal"></div>
Javascript
var myInputs = document.getElementById('myInputs'),
myTotal = document.getElementById('myTotal'),
order = {
total: 0
},
items = {
foo: {
1: 0.5,
100: 0.25
},
bar: {
1: 1,
100: 0.5
}
},
totalNode;
function calculateTotal() {
var newTotalNode;
Object.keys(order).filter(function (key) {
return key !== 'total';
}).reduce(function (acc, key) {
order.total = acc + order[key].subTotal;
return order.total;
}, 0);
newTotalNode = document.createTextNode(order.total.toFixed(2));
if (totalNode) {
myTotal.replaceChild(newTotalNode, totalNode);
totalNode = newTotalNode;
} else {
totalNode = myTotal.appendChild(newTotalNode);
}
console.log(JSON.stringify(order));
}
calculateTotal();
Object.keys(items).forEach(function (key) {
var div = document.createElement('div'),
label = document.createElement('label'),
price = document.createElement('span'),
input = document.createElement('input'),
subtotal = document.createElement('span'),
priceNode,
subTotalNode;
order[key] = {
quantity: 0,
subTotal: 0,
price: items[key]['1']
};
priceNode = document.createTextNode(order[key].price.toFixed(2));
subTotalNode = document.createTextNode(order[key].subTotal.toFixed(2));
label.className = 'itemLabel';
label.setAttribute("for", key);
label.appendChild(document.createTextNode(key));
price.className = 'currentPrice';
price.id = key + 'CurrentPrice';
price.appendChild(priceNode);
input.id = key;
input.name = 'myFormGroup';
input.type = 'text';
input.addEventListener('change', (function (key, order, priceNode, subTotalNode) {
return function () {
var value = +(this.value),
newPriceNode,
newSubTotalNode;
Object.keys(items[key]).sort(function (a, b) {
return b - a;
}).some(function (quantity) {
if (value >= quantity) {
order.price = items[key][quantity];
newPriceNode = document.createTextNode(order.price.toFixed(2));
priceNode.parentNode.replaceChild(newPriceNode, priceNode);
priceNode = newPriceNode;
return true;
}
return false;
});
order.subTotal = order.price * value;
newSubTotalNode = document.createTextNode(order.subTotal.toFixed(2));
subTotalNode.parentNode.replaceChild(newSubTotalNode, subTotalNode);
subTotalNode = newSubTotalNode;
calculateTotal();
};
}(key, order[key], priceNode, subTotalNode)), false);
subtotal.className = 'subTotal';
subtotal.id = key + 'SubTotal';
subtotal.appendChild(subTotalNode);
div.appendChild(label);
div.appendChild(price);
div.appendChild(input);
div.appendChild(subtotal);
myInputs.appendChild(div);
});
On jsFiddle
This is likely an easy fix (easy +200 reputation), for someone who has javascript skills.
Demo of problem: http://shoppingcart-bthub.blogspot.com/ Just add all the items to the cart and click refresh to see the problem with the cookies.
Everything works correctly, except the part of the code that handles cookies for the items that get added to the shopping cart. For some reason, it only holds 2 -5 items, depending on the broswer:
Google Chrome - only holds 2 items (all other items in shopping cart disappear after page reload)
Firefox - 4 items total
Safari - 4
Internet Exploer - 5
The javascript in the demo:
http://shopppingcart.googlecode.com/files/simplecart.js
The part of the javascript link above that is coded to handle cookies:
/*** data storage and retrival ****/
/* load cart from cookie */
me.load = function () {
var me = this;
/* initialize variables and items array */
me.items = {};
me.total = 0.00;
me.quantity = 0;
/* retrieve item data from cookie */
if( readCookie('simpleCart') ){
var data = unescape(readCookie('simpleCart')).split('++');
for(var x=0, xlen=data.length;x<xlen;x++){
var info = data[x].split('||');
var newItem = new CartItem();
if( newItem.parseValuesFromArray( info ) ){
newItem.checkQuantityAndPrice();
/* store the new item in the cart */
me.items[newItem.id] = newItem;
}
}
}
me.isLoaded = true;
};
/* save cart to cookie */
me.save = function () {
var dataString = "";
for( var item in this.items ){
dataString = dataString + "++" + this.items[item].print();
}
createCookie('simpleCart', dataString.substring( 2 ), 30 );
};
To test the full live code:
For the complete live template with all the codes, open a free blog at blogger.com and download the XML template here to upload into blogger: http://www.bloggermint.com/2011/05/shopping-cart-blogger-template/ The free download is in the left-hand sidebar. Also follow the intructions on that page to get it woking in blogger.com
In my opinion the problem is related to the 4K cookie size limit.
Your shopppingcart code is trying to store all the items data in a simpleCart cookie, but when such data gets bigger than 4K the items are not stored into the cookie, even if they're showed in the cart, therefore when the page is reloaded those items disappear.
Consider for example the site http://shoppingcart-bthub.blogspot.in/, and specifically the HTML markup for the "Sony VAIO laptop" item:
<table border="1" style="width: 660px;">
<tbody>
<tr>
<th class="item_thumb" id="thumb" width="45%"><img border="0" src="http://3.bp.blogspot.com/-LcQD--Bb_YE/TeDI44AmUsI/AAAAAAAACBw/K4IJZE2CpMY/s1600/sony+vaio.JPG"></th>
<td>
<input class="item_add" type="button" value="Add to Cart" id="s1">
</td>
</tr>
<tr>
<th><b>Item Name</b></th>
<td class="item_name">Sony VPCEE42FX 15.5" 2.30GHz 500GB VAIO Laptop</td>
</tr>
<tr>
<th><b>Price</b></th>
<td class="item_price">$610.00</td>
</tr>
<tr>
<th><b>Description</b></th>
<td class="item_Description">
The VPCEE42FX is big enough to be useful, but small
enough to be portable. With 500GB of hard drive space, youll have to work hard
to fill up the memory. The 15.5 HD resolution screen and AMD Mobility Radeon HD
graphics card ensure that youll see crisp, fast action, even when youre watching
DVDs on the DVD drive. And at under six pounds, the laptop is easy to pack up
and haul with you.
</td>
</tr>
<tr>
<th><b>Available Stock</b></th>
<td>2 more available</td>
</tr>
</tbody>
</table>
When this product is added to the cart, the simpleCart cookie will contain the following string:
id=c10||thumb=%3Cimg%20border%3D%220%22%20src%3D%22http%3A//3.bp.blogspot.com/-LcQD--Bb_YE/TeDI44AmUsI/AAAAAAAACBw/K4IJZE2CpMY/s1600/sony+vaio.JPG%22%3E%0A||name=Sony%20VPCEE42FX%2015.5%22%202.30GHz%20500GB%20VAIO%20Laptop||price=610||description=The%20VPCEE42FX%20is%20big%20enough%20to%20be%20useful%2C%20but%20small%20enough%20to%20be%20%0Aportable.%20With%20500GB%20of%20hard%20drive%20space%2C%20youll%20have%20to%20work%20hard%20to%20%0Afill%20up%20the%20memory.%20The%2015.5%20HD%20resolution%20screen%20and%20AMD%20Mobility%20%0ARadeon%20HD%20graphics%20card%20ensure%20that%20youll%20see%20crisp%2C%20fast%20action%2C%20even%20%0Awhen%20youre%20watching%20DVDs%20on%20the%20DVD%20drive.%20And%20at%20under%20six%20pounds%2C%20the%20%0Alaptop%20is%20easy%20to%20pack%20up%20and%20haul%20with%20you.||quantity=1
As you can see, it seems that all the <td> elements with a class name starting with item_ are stored in the cookie.
Chrome Developer's Tools shows a size of 828 bytes for this cookie.
Therefore the number of the items that can be added to the cart is variable and depends by the length of each item data (name, description, etc.).
So, what can you do to avoid this problem?
Reduce the item HTML markup to the minimum, for example by removing the item_thumb and item_Description elements.
Modify the addToCart method in the simplecart.js code to reduce the lenght of the cookie by storing less information (see below for details).
Modify the createCookie, readCookie and eraseCookie functions in the simplecart.js code to use local storage instead of a cookie to store item data (have a look at this page for a code sample, or below for another example).
For example, to avoid the storing of the "thumb" and "Description" item fields in the cookie, you could modify the addToCart method as follows:
ShelfItem.prototype.addToCart = function () {
var outStrings = [],valueString;
for( var field in this ){
if( typeof( this[field] ) != "function" && field != "id" ){
valueString = "";
//console.log(field);
switch(field){
case "price":
if( this[field].value ){
valueString = this[field].value;
} else if( this[field].innerHTML ) {
valueString = this[field].innerHTML;
}
/* remove all characters from price except digits and a period */
valueString = valueString.replace( /[^(\d|\.)]*/gi , "" );
valueString = valueString.replace( /,*/ , "" );
break;
case "image":
valueString = this[field].src;
break;
case "thumb":
case "Description":
case "description":
/* don't store "thumb" and "description" in the cookie */
break;
default:
if( this[field].value ){
valueString = this[field].value;
} else if( this[field].innerHTML ) {
valueString = this[field].innerHTML;
} else if( this[field].src ){
valueString = this[field].src;
} else {
valueString = this[field];
}
break;
}
outStrings.push( field + "=" + valueString );
}
}
}
A much better approach would be to use localStorage if the browser supports it, otherwise use cookies as a fallback:
function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}
function createCookie(name,value,days) {
if (supports_html5_storage()) {
if (value == '') {
eraseCookie(name);
} else {
window.localStorage.setItem(name, JSON.stringify(value));
}
} else {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
}
function readCookie(name) {
if (supports_html5_storage()) {
return window.localStorage.getItem(name);
} else {
var ca = document.cookie.split(';');
var nameEQ = name + "=";
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
}
function eraseCookie(name) {
if (supports_html5_storage()) {
window.localStorage.removeItem(name);
} else {
createCookie(name,"",-1);
}
}
When using localStorage we can also store the thumb and description fields without problems (since we have 5 Mb of space), therefore we can further modify the ShelfItem.prototype.addToCart function this way:
...
case "thumb":
case "Description":
case "description":
if (!supports_html5_storage()) break;
...
It seems you are catching black cat in a dark room and cat isn't there.
So what I've done:
Get http://shopppingcart.googlecode.com/files/simplecart.js
Get html from http://wojodesign.com/simpleCart/
Replace simplecart.js with yours.
What I've found:
When you open html page from filesystem then you have what you have
If you put it on a server (in my case local instance of apache) then everything works fine
2 Episode.
You trying to put to much information in cookie.
Simple way modify print function like this
CartItem.prototype.print = function () {
var returnString = '';
for( var field in this ) {
if( typeof( this[field] ) != "function" && field !="description") {
returnString+= escape(field) + "=" + escape(this[field]) + "||";
}
}
return returnString.substring(0,returnString.length-2);
};
Do you really need all item fields in cookie?
I'm trying to figure out the code behind looking at a new Sales Order that has an item called "Repair" and add a second item called "Repair Cost" before User submit. I'm a bit lost and I welcome any help that can be given. I would like this script to be in Javascript and I will attach it to the Sales Order form in Netsuite to run.
Here is one sample solution:
We will still assume that the items internal ids are Repair = 100 and Repair Cost = 200
function recalc(type)
{
if(type == 'item')
{
var itemId = nlapiGetCurrentLineItemValue('item', 'item'); //Get the Item ID
if(itemId == 100) //Repair Cost
{
//Insert item
nlapiSelectNewLineItem('item');
nlapiSetCurrentLineItemValue('item', 'item', 200); //Repair Cost
nlapiSetCurrentLineItemValue('item', 'quantity', 1);
nlapiSetCurrentLineItemValue('item', 'amount', '0.00');
nlapiCommitLineItem('item');
}
}
return true;
}
Deploy this as client-side code and make sure that the function is Recalc.
To learn more about client side script: https://system.na1.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteFlex/SuiteScript/SSScriptTypes_ClientScripts.html#1016773
First thing you need to do is to get the internal id of the item "Repair" and "Repair Cost".
In this example, let's assumed that the internal id of Repair = 100 and Repair Cost = 200
Here is th code:
function afterSubmit(type)
{
if(type == 'create' || type == 'edit')
{
var record = nlapiLoadRecord(nlapiGetRecordType(), nlapiGetRecordId()); //Load the record
//Loop to all sublist item
var count = record.getLineItemCount('item');
for(var i = 1; i <= count; i++)
{
var item = record.getLineItemValue('item', 'item', i); //This will return the internal id of the item
if(item == 100) //Item is equal to 100; insert one item
{
record.insertLineItem('item', i);
record.setLineItemValue('item', 'item', i, 200); //Repair Cost internal id
record.setLineItemValue('item', 'quantity', i, 1); //You should put some quantity; depending on your account setup all required fields should be set here.
}
}
//Submit the changes
nlapiSubmitRecord(record, true);
}
}
To understand the suitescript API and the fields exposed to sales order check on this Netsuite helpguide:
https://system.netsuite.com/help/helpcenter/en_US/RecordsBrowser/2012_2/Records/salesorder.html