Push to array inside a for in Javascript - javascript

I have an object, this.items, that I am running a for in on, then using the find method to get all the products by id. I'm attempting to set a salesTax amount based on a conditional (if taxPercent > 0), but the loop is going through more than the expected amount of times and thus the taxPercent is larger than required.
total() {
let total = 0
let tax = []
let importDuty = .05
for (let productId in this.items) {
total += this.inventory.products.find(product => {
if (product.taxPercent > 0) {
tax.push(product.price * product.taxPercent)
}
return product.id == productId
}).price * this.items[productId]
}
tax = tax.reduce((a, b) => a + b, 0)
let importDutyToApply = total * importDuty
total = total + importDutyToApply + tax
let response = {
'total': total,
'tax': tax
}
return response
}
I'm wondering how I can set the total tax to apply for any items that do not have the taxPercent set to 0. So, if I had three items and one of them required a 10 percent tax on $100, the total should be $10. Likewise if I had many items with some requiring the 10 percent tax and others not, it would only add up for the ones that require it. Any thoughts?

The function you pass to find gets called a load of times. You just want to add tax for the product it found, not for everything it looked at on the way.
const product = this.inventory.products.find( product => product.id == productId );
if (product.taxPercent > 0) {
tax.push(product.price * product.taxPercent)
}
total += product.price * this.items[productId]

Related

Input Checkbox Only Updates One Value But Other Inputs Don't Update?

So I have this app I made where it calculates the menu items total and includes a $5 delivery fee. The problem is the 4th option only includes the $5 fee in the total, but the other 3 options don't include the fee
Here's my codepen
https://codepen.io/shodoro/pen/dydNopX
Why is my 4th option, the smoothie $4 the only input checkbox that adds the delivery fee correctly?
The first 3 options don't include the $5 delivery fee in the total and I don't know how to fix it
Here's my JS
function updatePrice() {
let items = 0;
let deliveryFee = document.getElementById('fee')
let tax = document.getElementById('tax')
let tip = document.getElementById('tip')
tax = .1
tip = .2
document.querySelectorAll('input[type=checkbox]').forEach(checkBox => {
if (checkBox.checked) {
items += +checkBox.value
deliveryFee = 5
} else {
deliveryFee = 0
}
})
document.getElementById("price").textContent = `Food Total: $${(items).toFixed(2)}`;
document.getElementById("tax").textContent = `Tax (10%): $${(items * tax).toFixed(2)}`;
document.getElementById("tip").textContent = `Tip (20%): $${(items * tip).toFixed(2)}`;
document.getElementById("total").textContent = `Your order total is: $${((items * tax)+(items * tip)+(items)+(deliveryFee)).toFixed(2)}`;
}
Essential I want all options to include the delivery fee when clicking them, but also making sure the delivery fee resets to 0 whenever you uncheck all options.
That's because you are setting deliveryFee in a loop and so if, for example, the 12 piece wings item is checked, then it sets deliveryFee to 5 and then it's going to loop through to the next item (6 piece wings) and it will set deliveryFee to 0. So when it gets to the calculation for the total, it deliveryFee will be 0 and not 5. I think maybe you want something more like this:
function updatePrice() {
console.log('updatePrice');
let items = 0;
let deliveryFee = 0;
let tax = document.getElementById('tax')
let tip = document.getElementById('tip')
tax = .1
tip = .2
console.log('before forEach loop', items, deliveryFee);
document.querySelectorAll('input[type=checkbox]').forEach(checkBox => {
console.log(checkBox);
if (checkBox.checked) {
console.log('checked!')
items += +checkBox.value
if (deliveryFee == 0) {
console.log('First checked item, setting delivery fee to 5.')
deliveryFee = 5;
}
} else {
console.log('not checked!');
}
})
console.log('after forEach loop', items, deliveryFee);
if (items >= 10) {
deliveryFee = deliveryFee * 2;
}
let orderTotal = (items * tax)+(items * tip)+(items) + deliveryFee;
document.getElementById("price").textContent = `Food Total: $${(items).toFixed(2)}`;
document.getElementById("tax").textContent = `Tax (10%): $${(items * tax).toFixed(2)}`;
document.getElementById("tip").textContent = `Tip (20%): $${(items * tip).toFixed(2)}`;
document.getElementById("fee").textContent = `Delivery Fee: $${deliveryFee.toFixed(2)}`;
document.getElementById("total").textContent = `Your order total is: $${orderTotal}`;
}

How do I filter the data sent by firestore

How do I filter the data in collection in Firestore
If the first letter is "+" then I want to get filtered in Income section if the first letter is "-" then I want to get filtered in Expenditure Section
I tried this, but not working:
const getUsers = async()=>{
total_income_amount = await db.collection("users").get().then((querySnapshot) => {
const sum = querySnapshot.docs.filter((item) => item > 0).reduce((a, b) => a + b.data().amount, 0)
return sum
})
}
I am getting the output as 0
and I want the output with two decimal places
EDIT
Here's my code:
total_amount = db.collection("users").get().then((querySnapshot) => {
var total_sum = 0;
var income_sum = 0;
var exp_sum = 0;
querySnapshot.docs.forEach(doc => {
const amount = doc.data().amount;
amount >= 0.0? income_sum += amount : exp_sum -= amount;
total_sum += amount;
});
return {total: total_sum, income: income_sum, expense: exp_sum }
}).finally(result => console.log("Total: ", result));
You can loop through the list of values and append the values once rather than looping through it 5 times with a reduce & filter
total_amount = db.collection("users").get().then((querySnapshot) => {
var total_sum = 0;
var income_sum = 0;
var exp_sum = 0;
querySnapshot.docs.forEach(doc => {
const amount = doc.data().amount;
amount >= 0.0? income_sum += amount : exp_sum -= amount;
total_sum += amount;
});
return {total: total_sum, income: income_sum, expense: exp_sum }
})
.finally(result => console.log("TOTALS", result);
EDIT
It's not good to make major changes to your Question
but in general, you can truncate all number's to a decimal place using toFixed() on the final output
https://www.w3schools.com/jsref/jsref_tofixed.asp
UPDATE
Ensure your numbers are converted to real numbers from user inputs with Number(value) if the typeof returned is not a number, you can know if it is valid or not.
Once this has been done, ensure you return the correct calls as needed as scripts also only fire once.
when rendering values inside HTML, you want to use an embedded <span> tag with the appropriate id tag rather than editing it via javascript

increment totalAmount each time add product

I have a problem when I add a product the totalAmount shows me 20 I don't know why? and if I increment the totalAmount doesn't move how can I do it?
thanks
ts.file
productList = [
{ id: 1, name: 'Louis Vuis', price: 10, qtn: 1 },
{ id: 2, name: 'shubert helmet', price: 20, qtn: 1 },
];
productArray: any = [];
totalAmount: number;
ngOnInit() {
this.totalPrice();
}
add(product, idx) {
const found = this.productArray.find(
item => JSON.stringify(item) === JSON.stringify(product)
);
if (found) {
this.productArray[idx].qtn++;
} else {
this.productArray.push(product);
}
}
totalPrice() {
this.productList.forEach(item => {
this.totalAmount = (item.qtn * item.price)
console.log(this.totalAmount);
});
}
The problem is somewhere else I feel. What you are doing is right
totalPrice() {
this.productList.forEach(item => {
this.totalAmount = (item.qtn * item.price)
console.log(this.totalAmount);
});
}
But you are iterating the javascript object and assigning the value to total amount.
So while Iterating if you want to show price of each Item based on quantity you need to assign the value within a new key of product.
Something Like item.total = (item.qtn * item.price);
Incase you want to display the sum of all value in totalAmount you will need to do this.totalAmount += (item.qtn * item.price)
and when you add Quantity increment the quantity by 1 that you are doing , update the state and call this.totalPrice()
There are multiple issues,
When adding a product you are adding that in productArray but when calculating totalAmount you are calculating from productList. This will give you constant totalAmount no matter how many product you add in the productArray.
this.totalAmount = (item.qtn * item.price) will reassign the updated value into totalAmount instead of adding to the previous value. You need to write, this.totalAmount += (item.qtn * item.price)
From my understanding I am updating the totalPrice method. Not sure if it will help or not,
totalPrice() {
this.productList.forEach(item => {
let productIndexInProductArray = productArray.findIndex(p => p.id === item.id);
if(productIndexInProductArray > -1) {
this.totalAmount += (productArray[productIndexInProductArray].qtn * item.price)
console.log(this.totalAmount);
}
});
}
totalAmount: number=0;
this.totalAmount += (item.qtn * item.price)
Problem is totalAmount id define but not initialized
So first change is need to initialize totalAmount
totalAmount: number = 0;
Second change is need to do in totalPrice function because every time when you calculate amount that item amount set to totalAmount so totalAmount reset with every item that why you get last item amount in console. you need to add item amount in totalAmount like below
totalPrice() {
this.productList.forEach(item => {
this.totalAmount += (item.qtn * item.price)
console.log(this.totalAmount);
});
}

Application that calculates price depending on quantity in JavaScript

I have this exercise that I am struggling to comprehend the logic to achieve the outcome when qty is more than 3:
An application to calculate the price of pizzas (listed below) that will be purchased during a promotional period. The number of pizzas will be entered by the user.
One large pizza will cost $6.45.
Two large pizzas will cost $12.00.
Three large pizzas will cost $14.00.
Four or more pizzas will use a combination of the above prices to ensure the best price for the customer. For example, the best price for five pizzas would be two pizzas ($12.00) + three pizzas ($14.00).
The algorithm must also take account of all possible situations by using sequence, selection and iteration structures.
Below is my code so far:
let calcOrder = () => {
// get inputs
var qty = document.getElementById("quantity").value;
var price = 6.45;
var price2 = 12.0;
var price3 = 14.0;
var totalPrice;
// validate missing, non-digit, negative inputs
if (qty == "") {
document.getElementById("message").innerHTML = "Missing input";
} else if (isNaN(qty)) {
document.getElementById("message").innerHTML = "Numbers only";
} else if (qty < 0) {
document.getElementById("message").innerHTML =
"Negative numbers are not allowed";
} else {
//calc total
if (qty == 1)
{
totalPrice = price;
}
else if (qty == 2)
{
totalPrice = price2;
}
else if (qty == 3)
{
totalPrice = price3;
}
//output total
document.getElementById("message").innerHTML =
`Total price is $${totalPrice}`;
}
// prevent form from submission
return false;
};
Thank you
you can use division and mod operation to calculate the price:
(this example assuming all check you did valid input are already done)
const qte = document.getElementById("quantity").value;
const price = 6.45;
const price2 = 12.0;
const price3 = 14.0;
let totalPrice;
const total3 = parseInt("" + qte / 3 + "", 10) * price3;
const total2 = parseInt("" + (qte % 3) / 2 + "", 10) * price2;
const total1 = parseInt("" + ((qte % 3) % 2) + "", 10) * price;
totalPrice = total1 + total2 + total3;
document.getElementById("message").innerHTML =
`Total price is $${totalPrice}`;
what is actually happening in the code
well it is basic mathematics, if you want to know how many 3s in your number you divide by 3 and take the integer part or floor of the result, basic division. for example 10 = 3*3 + 1 so you have 3 as a result of that division.
since you only want to apply the price of 3 pizza as top priority you do this division then multiply by the price for 3.
then come the priority for the price of 2 pizzas, but you not interested for the total number of pizzas, only what was left after you payed with the price of 3 pizzas so you do the mod operator (%) with 3 to get was left unpaid, for example 8 = 3*2 + 2, this give us 2 pizzas left unpaid so you apply the price of 2 pizzas.
the you check if a single pizza is left after you paid for 2 pizzas (which would only happen if only a single pizza was left after you paid for 3). if there is single pizza you pay for it otherwise you add nothing.
ps: after paying for pizzas in multiple of three, you only add the price of 2 pizzas or a single one, but never both, otherwise price of 3 pizzas would apply instead.
hope the explanation is clear, if not leave a comment and i'll try to adjust what was not clear.

Can I force percentages to sum up to a exact value?

I have a fixed tax value, say USD 50,00, and I want to divide this tax among people. So, one person can select how much of the tax he will pay. Once this person selects its quota, the remaining of the tax is divided among the others.
I have made a javascript(I am using EmberJs) function to do this automatically but sometimes the value is evaluated to more than USD 50 and sometimes less.
My function:
percentageFromValue(person, selectedValue){
selectedValue = selectedValue.replace(/[R$\s]/g,'');
selectedValue = selectedValue.replace(/[,]/g,'.');
selectedValue = parseFloat(selectedValue);
let taxValue= this.get('taxValue');
///nao deixar valor utrapasse o valor da taxa
if(selectedValue> taxValue)
valor = taxValue;
let personPercentage = (selectedValue*100.0 / taxValue);
personPercentage = parseFloat(personPercentage );
let parcialSum= 0;
person.set('pctTax',personPercentage.toFixed(2));
let remainingPercent= 100.0 - personPercentage ;
let totalPersons = this.get('persons.length');
let pctPerPerson= remainingPercent/ (totalPersons - 1);
let valuePerPerson= (pctPerPerson* taxValue) / 100.0;
this.get('persons').forEach(r =>{
if(person.get('id') != r.get('id')){
r.set('pctTax',pctPerPerson);
r.set('value',valuePerPerson.toFixed(2));
}
});
},
How Can I make this automatic redistributions to always sum up to USD 50,00??
This is more of a rounding problem than a programming problem.
Say you want to divide a $50 tax among three people... 50/3 = 16.6666666... assuming it's a currency and you round up to two decimals, each person pays $16.66 and the sum is 16.66 * 3 = 49.98.
If there is no requirement of having all people paying the exact same amount of tax every time, I'd just add/subtract the rounding difference from the first person:
let remainingPercent= 100.0 - personPercentage ;
let totalPersons = this.get('persons.length');
let pctPerPerson= remainingPercent/ (totalPersons - 1);
let valuePerPerson= (pctPerPerson* taxValue) / 100.0;
let roundingError = taxValue - pctPerPerson * totalPersons;
this.get('persons').forEach(r =>{
if(person.get('id') != r.get('id')){
r.set('pctTax',pctPerPerson);
if (this.indexOf(r) == 0) {
r.set('value',valuePerPerson.toFixed(2) + roundingError);
} else {
r.set('value',valuePerPerson.toFixed(2));
}
}
});

Categories

Resources