how calculate automatically the price of some woocommerce selected products - function

Im trying to get the total price depend by selected products.
ex.
3 products images (woocommerce classic layout)
clicking for ex.on 2 products I get the sum of the price in a box below which then takes me to the cart.
But I don't know how to solve this problem (in html I get nothing), here's the function and the script.
function calculate_total_price() {
// ID array of the selected products from the page
$selected_products = $_POST['selected_products'];
// Initialize the total price to 0
$total = 0;
// foreach selected product ID
foreach ($selected_products as $product_id) {
// get the product ID
$product = wc_get_product($product_id);
// Add the total price
$total += $product->get_price();
}
// Return the total price
return $total;
}
jQuery(document).ready(function($) {
// click and calculate
$('#calculate-total-button').click(function(e) {
e.preventDefault();
// ID array of the selected products
var selected_products = [];
$('.selected-product').each(function() {
selected_products.push($(this).data('product-id'));
});
// send this ajax request to the function
$.ajax({
url: '/wp-admin/admin-ajax.php',
type: 'POST',
data: {
action: 'calculate_total_price',
selected_products: selected_products
},
success: function(total) {
// Display the total price on the page
$('#total-price').text(total);
}
});
});
});
Many thanks

Related

JSON add nested sub objects dynamically using JS or JQuery

I am creating a services cart at client side
where services are grouped inside 3 level of groupings like
product[SECTION] [SERVICE] [ITEM]
product['carpet']['cleaning']['room'] = {'qty':2,'price':15};
product['carpet']['cleaning']['hall'] = {'qty':1,'price':10};
product['carpet']['protecting']['hall'] = {'qty':1,'price':10};
product['carpet']['deodorize']['hall'] = {'qty':1,'price':10};
product['leather']['cleaning']['sofa'] = {'qty':1,'price':10};
want to generate above structure of json.
my text boxes looks like below notice data-section data-service data-tem and data-price
<input type="text" class="form-control input-number"
data-price="15" data-section="carpet" data-item="room" data-service="protect" />
My JS code is as below, but it adds only current item while overwriting all other services and sections.
$(function(){
$('.input-number').change(function(){
var section = $(this).attr('data-section');
var item = $(this).attr('data-item');
var service = $(this).attr('data-service');
var qty = $(this).val();
var unitprice = $(this).attr('data-unitprice');
addProduct(section,item,service,qty,unitprice);
});
});
function addProduct(section,item,service,qty,unitprice){
let products = {};
if(localStorage.getItem('products')){
products = JSON.parse(localStorage.getItem('products'));
}
products['"'+section+'"'] =
{
['"'+service+'"'] : {
['"'+item+'"'] : {
'unitprice' : unitprice, 'qty': qty
}
}
};
localStorage.setItem('products', JSON.stringify(products));
}
How can I append only instead of overwriting nested items?
EDITED
I have edited my add product function as below but still not getting desired result
function addProduct(section,item,service,qty,unitprice){
let products = {};
if(localStorage.getItem('products')){
products = JSON.parse(localStorage.getItem('products'));
}
var v = {
[service] : {
[item] :{
"qty":qty,'unitprice':unitprice
}
}
};
products.push( section, v );
localStorage.setItem('products', JSON.stringify(products));
}
Object.prototype.push = function( key, value ){
if(typeof value === 'object'){
var k = Object.keys(value)[0];
value.push( k, value[k] );
}
this[ key ] = value;
return this;
}
First of all that is not a good way to store your data.
Here's a better way to store your data.
It's much more easy to understand if you see it like an object cause in javascript it's the same thing
//example this 2 data is store the same way in javascript
var product['carpet']['cleaning']['room'] = {'qty':2,'price':15};
var product = [{
carpet: {
cleaning: {
room: {'qty':2,'price':15}
}
}
}]
// my solution would be just save section, service and item in the object, example:
var product = [];
var v = {
section: 'carpet',
service: 'cleaning',
item: 'room'
qty:2,
price:15
}
product.push(v)

Problems with decimal column in webshop

In a webshop product table, i have a column, called minimum_order. This is the minimum quantity, that i can order from this product.
If i give 1 for this data, it stores that in the table like 1.00. The column type is decimal, 10.2
On my product page, when i want to add it to the basket, i get an error, that i cant order 1 of this product, because the minimum order is 1.00
What am i doing wrong?
Update:
So i echo the minimum order value of the product to a hidden input.
<input type="hidden" value="'.$kat['termek_min_order'].'" id="MinimumOrder'.intval($kat['termek_id']).'">
In the browser when i view the source, that inputs value is 1.00
Add to cart with javascript:
function add_to_cart(termek_id)
{
var darabszam = $.trim($('#item_darabszam'+termek_id).val()); // The quantity i typed in, that i want to order
var MinimumOrder = $.trim($('#MinimumOrder'+termek_id).val()); // The minimum order value
var CartErrors = [];
if(darabszam == "") { CartErrors.push("No value, or 0 was typed."); }
if(darabszam < MinimumOrder) { CartErrors.push("The minimum order of this product is "+MinimumOrder+"."); }
if(CartErrors.length == 0 )
{
$.ajax({
type: 'POST',
url: 'files/add_to_kosar.php',
data: { termek_id: termek_id, darab: darabszam, MinimumOrder: MinimumOrder },
dataType: "html",
cache: false,
timeout: 10000,
success: function(data)
{
kosartetelek();
var result = $.trim(data);
$('#CartModalResult').html(data);
$('.CartModalTitle').html('Added to basket ok');
$('#CartModal').modal('show');
checkprice();
}
});
}
else
{
$('.CartModalTitle').html('Error while adding to basket.');
$('#CartModalResult').fadeIn('slow').html('<div class="javascript_error_div">'+(CartErrors.join('<br/>'))+'</div>');
$('#CartModal').modal('show');
}
setTimeout(function()
{
$('#CartModal').modal('hide');
}, 10000 );
}
So at this product, if i want to order 1, i get an error, that i have to order minium 1.00
Do i really need decimal typed column for this? What does the float type column do?

In-App purchases not working in chrome extension

The In-App purchases screen is returning:
Screenshot of In-App screen
The error is:
An unexpected error has occurred. Please try again later. Dismiss
And as you can see, half of it is also black.
Buy.js:
/*GOOGLE's CODE
...
*/
/*CODE FOR IN-APP PURCHASES*/
var prodButPrefix = "btnProdID-";
var statusDiv;
function init() {
console.log("App Init");
statusDiv = $("#status");
// getProductList();
}
$("#div1").click(function() {
checkIfBought("package2016");
});
/*****************************************************************************
* Get the list of purchased products from the Chrome Web Store
*****************************************************************************/
var purchased = false;
function getLicenses() {
console.log("google.payments.inapp.getPurchases");
console.log("Retreiving list of purchased products...");
google.payments.inapp.getPurchases({
'parameters': {env: "prod"},
'success': onLicenseUpdate,
'failure': onLicenseUpdateFailed
});
}
function checkIfBought(sku_init){
getLicenses();
function getLicenses() {
console.log("google.payments.inapp.getPurchases");
console.log("Retreiving list of purchased products...");
google.payments.inapp.getPurchases({
'parameters': {env: "prod"},
'success': onLicenseUpdate,
'failure': onLicenseUpdateFailed
});
}
function onLicenseUpdate(response) {
console.log("onLicenseUpdate", response);
var licenses = response.response.details;
var count = licenses.length;
for (var i = 0; i < count; i++) {
var license = licenses[i];
if(sku_init == licenses[i].response.details.sku){ //if purchased
purchased = true;
}
addLicenseDataToProduct(license);
}
console.log("");
}
function onLicenseUpdateFailed(response) {
console.log("onLicenseUpdateFailed", response);
console.log("Error retreiving list of purchased products.");
}
if(purchased == false){
buyProduct("package2016");
}
}
/*****************************************************************************
* Purchase an item
*****************************************************************************/
function buyProduct(sku) {
console.log("google.payments.inapp.buy", sku);
//var sku = "";
google.payments.inapp.buy({
'parameters': {'env': 'prod'},
'sku': sku,
'success': onPurchase,
'failure': onPurchaseFailed
});
}
function onPurchase(purchase) {
console.log("onPurchase", purchase);
var jwt = purchase.jwt;
var cartId = purchase.request.cardId;
var orderId = purchase.response.orderId;
console.log("Purchase completed. Order ID: " + orderId);
getLicenses();
}
function onPurchaseFailed(purchase) {
console.log("onPurchaseFailed", purchase);
var reason = purchase.response.errorType;
console.log("Purchase failed. " + reason);
}
This is what is being printed in the console:
google.payments.inapp.buy package2016
When I close the In-App payment screen this is printed:
onPurchaseFailed Object {request: Object, response: Object}
Purchase failed. PURCHASE_CANCELED
I emailed Chrome Dev support, they said:
In the Chrome Web Store, You are not allowed to purchase your own
Apps/Extensions. In order to test your item, you need to access it
from different account you have. (Not from your developer account).
You may have to make sure that you do not change/update the extension-id(nmmhkkegccagdldgiimedpiccmgmieda) in buy.js that they provide.
Also, please stringify the onPurchaseFailed Object and share it so I can help confirm the issue.

How can I do this asyn feature in nodejs

I have a code to do some calculation.
How can I write this code in an asyn way?
When query the database, seems we can not get the results synchronously.
So how to implement this kind of feature?
function main () {
var v = 0, k;
for (k in obj)
v += calc(obj[k].formula)
return v;
}
function calc (formula) {
var result = 0;
if (formula.type === 'SQL') {
var someSql = "select value from x = y"; // this SQL related to the formula;
client.query(someSql, function (err, rows) {
console.log(rows[0].value);
// *How can I get the value here?*
});
result = ? // *How can I return this value to the main function?*
}
else
result = formulaCalc(formula); // some other asyn code
return result;
}
Its not possible to return the result of an asynchronous function, it will just return in its own function scope.
Also this is not possible, the result will always be unchanged (null)
client.query(someSql, function (err, rows) {
result = rows[0].value;
});
return result;
Put a callback in the calc() function as second parameter and call that function in the client.query callback with the result
function main() {
calc(formula,function(rows) {
console.log(rows) // this is the result
});
}
function calc(formula,callback) {
client.query(query,function(err,rows) {
callback(rows);
});
}
Now if you want the main to return that result, you also have to put a callback parameter in the main and call that function like before.
I advice you to check out async its a great library to not have to deal with this kind of hassle
Here is a very crude way of implementing a loop to perform a calculation (emulating an asynchronous database call) by using events.
As Brmm alluded, once you go async you have to go async all the way. The code below is just a sample for you to get an idea of what the process in theory should look like. There are several libraries that make handling the sync process for asynch calls much cleaner that you would want to look into as well:
var events = require('events');
var eventEmitter = new events.EventEmitter();
var total = 0;
var count = 0;
var keys = [];
// Loop through the items
calculatePrice = function(keys) {
for (var i = 0; i < keys.length; i++) {
key = keys[i];
eventEmitter.emit('getPriceFromDb', {key: key, count: keys.length});
};
}
// Get the price for a single item (from a DB or whatever)
getPriceFromDb = function(data) {
console.log('fetching price for item: ' + data.key);
// mimic an async db call
setTimeout( function() {
price = data.key * 10;
eventEmitter.emit('aggregatePrice', {key: data.key, price: price, count: data.count});
}, 500);
}
// Agregate the price and figures out if we are done
aggregatePrice = function(data) {
count++;
total += data.price;
console.log('price $' + price + ' total so far $' + total);
var areWeDone = (count == data.count);
if (areWeDone) {
eventEmitter.emit('done', {key: data.key, total: total});
}
}
// We are done.
displayTotal = function(data) {
console.log('total $ ' + data.total);
}
// Wire up the events
eventEmitter.on('getPriceFromDb', getPriceFromDb);
eventEmitter.on('aggregatePrice', aggregatePrice);
eventEmitter.on('done', displayTotal);
// Kick of the calculate process over an array of keys
keys = [1, 2, 3]
calculatePrice(keys);

HTML5 Sequential execution

I have created a web storage for product details (productId, name, quantityonhand) and have populate records into it from the server. I have to validate whether the required quantity is available to accept the order.
The Product form has checkboxes (with name="product") for every product available in the web storage and a corresponding text input field to accept the quantity required.
The validation method is defined as follows.
function productValidation(){
for(i=0;i<document.Products.product.length;i++){
// checking whether the product has been checked / choosen
if (document.Products.product[i].checked==true){
var productId = document.Products.product[i].value;
var qty = document.Products.p[i].value;
var db = systemDB;
// validating the available quantity
db.transaction(
function(transaction){
transaction.executeSql('select * from product where productId=?;',
[productId],
function(transaction, results){
for (var j=0; j<results.rows.length; j++) {
var row = results.rows.item(j);
if (qty>row['qoh']){
alert(
row['productname']
+ ' is out of stock. We can serve you only '
+ row['qoh'] + ' quantities currently!');
document.Products.product[i].checked = false;
document.Products.p[i].value = 0;
}
}
});
}
);
}
}
return false;
}
When this code is executed, because of asynchronous nature of the db.transaction, the outer loop is getting executed and the validation is happening only for the last product choosen.
Help me to fix this. I want the execution happen sequentially.
Yuvi
Try chaining together calls in the callback function for db.transaction:
function productValidation(){
checkProductsSequential(document.Products.product, 0);
return false;
}
function checkProductsSequential(products, i)
{
if (i < products.length)
{
// checking whether the product has been checked / choosen
if (document.Products.product[i].checked==true){
var productId = document.Products.product[i].value;
var qty = document.Products.p[i].value;
var db = systemDB;
// validating the available quantity
db.transaction(
function(transaction){
transaction.executeSql('select * from product where productId=?;',
[productId],
function(transaction, results){
for (var j=0; j<results.rows.length; j++) {
var row = results.rows.item(j);
if (qty>row['qoh']){
alert(
row['productname']
+ ' is out of stock. We can serve you only '
+ row['qoh'] + ' quantities currently!');
document.Products.product[i].checked = false;
document.Products.p[i].value = 0;
}
}
checkProductsSequential(products, i + 1)
});
}
);
}
else
{
checkProductsSequential(products, i + 1)
}
}
}