Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

I’ve been trying to crack this problem for around a week and this is how much progress I have made so far. The parts I’m struggling to figure out are as follows.

#1: When change is owed, the cid won’t subtract the change from its drawer at all and update based off of that. The only idea that I have come up for this is amount -= currency.value. Does it have something to do with this or is there something else I’m not thinking about?

#2:I’m struggling to figure out why my cash register function isn’t correctly calculating the right denomination and it’s corresponding value in my change-due element. For example, if the change is 50 cents, then the textContent for the element will display PENNY: 0.49 instead of QUARTER: 0.50. For larger amounts of change like $20 it’ll say ONE: 9 instead of TWENTY: 20.

These are the main two problems that I can think of. If you see any other major issues that should be addressed then please let me know.

Your code so far

<!-- file: index.html -->
<input id="cash">
<div id="change-due"></div>
<button id="purchase-btn">Purchase</button>
<script src="script.js"></script>`
/* file: styles.css */

/* file: script.js */
let price = 1.87;
let cid = [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.1],
  ["QUARTER", 4.25],
  ["ONE", 90],
  ["FIVE", 55],
  ["TEN", 20],
  ["TWENTY", 60],
  ["ONE HUNDRED", 100]
];
let currencyUnit = [
  {name: "ONE HUNDRED", value: 100.0},
  {name: "TWENTY", value: 20.0},
  {name: "TEN", value: 10.0}, 
  {name: "FIVE", value: 5.0},
  {name: "ONE", value: 1.0},
  {name: "QUARTER", value: 0.25},
  {name: "DIME", value: 0.1},
  {name: "NICKEL", value: 0.05},
  {name: "PENNY", value: 0.01},
];
const cashInput = document.getElementById('cash');
const changeDue = document.getElementById('change-due');
const purchase = document.getElementById('purchase-btn');

purchase.addEventListener('click', exceptions);
purchase.addEventListener('click', checkCashRegister);

function exceptions() {
  if (parseFloat(cashInput.value) < price) {
    alert("Customer does not have enough money to purchase the item");
  } else if (parseFloat(cashInput.value) === price) {
    changeDue.textContent = "No change due - customer paid with exact cash";
  } else {
    checkCashRegister()
  }
}

function checkCashRegister() {
   let change = parseFloat(cashInput.value - price);
   let roundedChange = parseFloat(change.toFixed(2));

    let sumCid = 0;
    for (let element of cid) {
      sumCid += element[1]
    }
    let roundedCidSum = parseFloat(sumCid.toFixed(2));

    if (roundedCidSum < roundedChange) {
      changeDue.textContent = "Status: INSUFFICIENT_FUNDS"
      return;
    }
    if (roundedCidSum === roundedChange) {
      changeDue.textContent = `Status: CLOSED ${denomination}: ${amount}`;
      return;
    }
    
    cid = cid.reverse();

    for (let i = 0; i < cid.length; i++) {
        let denomination = cid[i][0];
        let amount = cid[i][1];
        let currency = currencyUnit.find(unit => unit.name === denomination);
        let value = 0;
        const currencyValue = parseFloat(Object.values(currencyUnit));
        const currencyName = Object.keys(currencyUnit);

while (roundedChange >= currency.value && amount > 0) {

            roundedChange -= currency.value;

             amount -= currency.value;

        value += currency.value;

let roundedValue = parseFloat(value.toFixed(2))

        changeDue.textContent = `Status: OPEN ${denomination} $${roundedValue}`

        if (roundedChange === 0 ) {
          break;
        }
           }
      
    }
}





Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0

Challenge Information:

Build a Cash Register Project - Build a Cash Register

This is a bit strange, I added console.log(denomination, amount) after the 57 line. The console is printing:

ONE HUNDRED 100
TWENTY 60
TEN 20
FIVE 55
ONE 90
QUARTER 4.25
DIME 3.1
NICKEL 2.05
PENNY 1.01
PENNY 1.01
NICKEL 2.05
DIME 3.1
QUARTER 4.25
ONE 90
FIVE 55
TEN 20
TWENTY 60
ONE HUNDRED 100

Any ideas why that’s repeated and in two different orders?

Could you specify what are price, cid and #cash values for these examples? It will help to see the exact same case as you did.

The whole order of the 2nd one is reversed because of this line cid = cid.reverse(). I was thinking that the cid needed to be in the same order as the currencyUnit object in order for the two to be able to work together smoothly.

As for the console logging twice… this is something that I forgot to mention in my list of issues. This one definitely stumped me too and when I investigated it via Google and StackOverflow, I couldn’t find a clear answer for it based on my code. The only sort of thing I found about it that might be the case is from a FCC forum a few years ago explaining that it’s a quirk in the test output on FCC.

I’ve set the price as the one that you’re initially given when you start the project which is 1.87. When the cash value is 2.37, my change value (which is indicated by the roundedChange variable ) comes out as 0.49 when it should be 0.50 and when it increments down to zero (from this line of code: roundedChange -= currency.value) it only increments down by the denomination value of a Penny which is 0.01 and it does that until roundedChange becomes zero. During these operations, nothing changes in the cid at all.

For the other example that I gave, price is still 1.87 and cash input is 21.87 (to result in a change value of 20), the change comes out as 19.99 and only increments down based on the value of a penny (0.01) until it reaches 19 then it starts incrementing down by the value of a nickel (0.05) until it reaches 17, then it increments down by 0.10, once it reaches 14 it increments down by 0.25 and once it reaches 10 it increments by 1 which is why you see ONE: 9 in the textContent. Still no change in cid and I tested a few other cases and nothing changes in cid either.

Sorry if this seems very overwhelming or quite strange. Take as much time as you need to understand everything. You can test it yourself by putting 21.87 in the input box (make sure price remains as 1.87), and adding console.log(roundedChange) and console.log(cid) inside of the while loop I have.

For a bit let’s assume it’s not some fCC quirk and try a more straightforward option. What if checkCashRegister is actually called twice in code?

I figured it out! It was that checkCashRegister call in my Exceptions function. I forgot about the function reference in the addEventListener.

Now that that’s fixed, I can move on to figuring out why the denomination is always subtracting the penny value from change before the others. My suspicion with that my currencyUnit object is starting off with the lowest value rather than the highest? Do I have the right idea or is there something else that I’m not noticing?

Have you checked that after removing second checkCashRegister call? I think the only moment when it actually could start with the pennies is the second call, when cid was being inverted again, to the initial order, which has pennies first.

Yep, but I think the reason I was seeing that issue still was because I removed cid = cid.reverse(). In your first response I thought you were pointing out to me that the cid reversal was problematic so I removed it at first, but I put it back and that specific issue is resolved.

This is my updated code

`let price = 3.26;
let cid = [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.1],
  ["QUARTER", 4.25],
  ["ONE", 90],
  ["FIVE", 55],
  ["TEN", 20],
  ["TWENTY", 60],
  ["ONE HUNDRED", 100]
];
let currencyUnit = [ 
  {name: "ONE HUNDRED", value: 100.0},
  {name: "TWENTY", value: 20.0},
  {name: "TEN", value: 10.0},
  {name: "FIVE", value: 5.0},
  {name: "ONE", value: 1.0},
  {name: "QUARTER", value: 0.25},
  {name: "DIME", value: 0.1},
  {name: "NICKEL", value: 0.05},
  {name: "PENNY", value: 0.01},
];
const cashInput = document.getElementById('cash');
const changeDue = document.getElementById('change-due');
const purchase = document.getElementById('purchase-btn');

purchase.addEventListener('click', exceptions);
purchase.addEventListener('click', checkCashRegister);

function exceptions() {
  if (parseFloat(cashInput.value) < price) {
    alert("Customer does not have enough money to purchase the item");
  } else if (parseFloat(cashInput.value) === price) {
    changeDue.textContent = "No change due - customer paid with exact cash";
}
}

function checkCashRegister() {
   let change = parseFloat(cashInput.value - price);
   let roundedChange = parseFloat(change.toFixed(2));

    let sumCid = 0;
    for (let element of cid) {
      sumCid += element[1]
    }
    let roundedCidSum = parseFloat(sumCid.toFixed(2));

    if (roundedCidSum < roundedChange) {
      changeDue.textContent = "Status: INSUFFICIENT_FUNDS"
      return;
    }
    if (roundedCidSum === roundedChange) {
      changeDue.textContent = `Status: CLOSED ${denomination}: ${amount}`;
      return;
    }
    
    cid = cid.reverse();

    for (let i = 0; i < cid.length; i++) {
         let denomination = cid[i][0];
        let amount = cid[i][1];
        let currency = currencyUnit.find(unit => unit.name === denomination);
        let value = 0;
        const currencyValue = parseFloat(Object.values(currencyUnit));
        const currencyName = Object.keys(currencyUnit);


while (roundedChange >= currency.value && amount > 0) {

            roundedChange -= currency.value;

             amount -= currency.value;

        value += currency.value;

        console.log(denomination, value)

        changeDue.textContent = `Status: OPEN ${denomination}: $${value}`

        if (roundedChange === 0 ) {
          break;
        }
           }
      
    }`

I’m now trying to figure out how to implement all the denominations and their corresponding amounts into my change due’s element so that I can pass this test when the price is 3.26 and the change is 100.
Screenshot_4-3-2024_115824_www.freecodecamp.org

I know that the resulting denominations and values need to be sorted from greatest to least, but when I try to sort the values with value.sort((a, b) => {a - b}),
I’m getting an error saying that value.sort is not a function and not sure what’s going on.

I’m not sure what value is at that time, but it would need to be array for it to work.

I’ll ask though, what is your goal with sorting the individual values?

When I set the cash input to 100 with the fixed price of 3.26, this is the result that I get.
Screenshot_5-3-2024_145137_www.freecodecamp.org

From that result, my thinking at first was that if the lowest denomination and value shows up first, then that could mean that they’re being sorted from least to greatest.

However, when testing what the console.log statement is for denomination and value I get this
Screenshot_5-3-2024_173713_www.freecodecamp.org

Which seems to be telling me that it isn’t a sorting issue since twenty is up top in the console, but it seems like textContent is being overwritten for each iteration of my while loop. With that in mind, I figured that I have to add new content to what already exists instead of replacing it until the loop finishes.

So I came up with: changeDue.textContent += Status: OPEN ${denomination}: $${value} The only thing I added here was the plus sign next to =

The result of that small change is this
Screenshot_5-3-2024_18341_www.freecodecamp.org

Which is on the right track since all the denoms/values show up, but I only want ‘Status: OPEN’ to show once, so I took that portion of the content out of the while loop and put it in a seperate textContent and updated the code like this.

changeDue.textContent = "Status: OPEN "

while (roundedChange >= currency.value && amount > 0) {

            roundedChange -= currency.value;

             amount -= currency.value;

        value += currency.value;

        console.log(denomination, value)

        changeDue.textContent += `${denomination}: $${value}`

        if (roundedChange === 0 ) {
          break;
        }
           }

But now all those denoms and values I had just disappeared.

Screenshot_5-3-2024_181126_www.freecodecamp.org

Once again, I tried using google for this, but I had a hard time figuring out how to phrase this problem in a way that doesn’t give away a full solution.

And this is all the progress I’ve made for this part today.

So it seems that the opening of the status is still not in the right place and getting replaced in some loop.

Oh whoops I forgot about the for loop above my while loop.

I took your advice and I now have managed to get it to this point.

Screenshot_6-3-2024_124923_www.freecodecamp.org

But as you can see it’s off by 1 cent since it says PENNY: 0.03 instead of 0.04.

I checked if the change calculation at the beginning of my cashRegister function is correct and it is since it displays 96.74 in the console.

I did notice that 0.04 doesn’t show up when console logging value which is strange since updating value seems to working properly since all the other values besides Penny are correct.

Other than that I have no clue where it could be coming from.

Could you share the updated code?

let price = 3.26;
let cid = [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.1],
  ["QUARTER", 4.25],
  ["ONE", 90],
  ["FIVE", 55],
  ["TEN", 20],
  ["TWENTY", 60],
  ["ONE HUNDRED", 100]
];
let currencyUnit = [ 
  {name: "ONE HUNDRED", value: 100.0},
  {name: "TWENTY", value: 20.0},
  {name: "TEN", value: 10.0},
  {name: "FIVE", value: 5.0},
  {name: "ONE", value: 1.0},
  {name: "QUARTER", value: 0.25},
  {name: "DIME", value: 0.1},
  {name: "NICKEL", value: 0.05},
  {name: "PENNY", value: 0.01},
];
const cashInput = document.getElementById('cash');
const changeDue = document.getElementById('change-due');
const purchase = document.getElementById('purchase-btn');

purchase.addEventListener('click', exceptions);
purchase.addEventListener('click', checkCashRegister);

function exceptions() {
  if (parseFloat(cashInput.value) < price) {
    alert("Customer does not have enough money to purchase the item");
  } else if (parseFloat(cashInput.value) === price) {
    changeDue.textContent = "No change due - customer paid with exact cash";
} else {
  changeDue.textContent = "Status: OPEN";
}
}

function checkCashRegister() {
   let change = parseFloat(cashInput.value - price);
   let roundedChange = parseFloat(change.toFixed(2));

    let sumCid = 0;
    for (let element of cid) {
      sumCid += element[1]
    }
    let roundedCidSum = parseFloat(sumCid.toFixed(2));

    if (roundedCidSum < roundedChange) {
      changeDue.textContent = "Status: INSUFFICIENT_FUNDS"
      return;
    }
    else if (roundedCidSum === roundedChange) {
      changeDue.textContent = `Status: CLOSED ${denomination}: ${amount}`;
      return;
    }
    
    cid = cid.reverse();

    for (let i = 0; i < cid.length; i++) {
         let denomination = cid[i][0];
        let amount = cid[i][1];
        let currency = currencyUnit.find(unit => unit.name === denomination);
        let value = 0;
        const currencyValue = parseFloat(Object.values(currencyUnit));
        const currencyName = Object.keys(currencyUnit);

while (roundedChange >= currency.value && amount > 0) {

            roundedChange -= currency.value;

             amount -= currency.value;

        value += currency.value;

        console.log(denomination, value)

        if (roundedChange === 0 ) {
          break;
        }
           }
      if (value > 0) {
        changeDue.textContent += ` ${denomination}: $${value}` 
      }
      
    }
}



That’s caused by the floating point error, if you add roundedChange to the console.log(denomination, value), it will show how for the last penny change is not enough.

I implemented your advice and now I have finally solved the whole project!!! Thank you so much!!! I really appreciate you helping me through every issue that I had. It’s likely that I’ll be back to posting when I’m working on the last project in the course :slight_smile:

1 Like

Could you give the code that you change to solve the problem cause i’m trying 2 days now and i cannot fix it…

We can help, if you tell us specifically with what you have troubles and share your code. For the convenience please start new thread.

let price = 3.26;
let cid = [
[“PENNY”, 1.01],
[“NICKEL”, 2.05],
[“DIME”, 3.1],
[“QUARTER”, 4.25],
[“ONE”, 90],
[“FIVE”, 55],
[“TEN”, 20],
[“TWENTY”, 60],
[“ONE HUNDRED”, 100]
];
let currencyUnit = [
{name: “ONE HUNDRED”, value: 100.0},
{name: “TWENTY”, value: 20.0},
{name: “TEN”, value: 10.0},
{name: “FIVE”, value: 5.0},
{name: “ONE”, value: 1.0},
{name: “QUARTER”, value: 0.25},
{name: “DIME”, value: 0.1},
{name: “NICKEL”, value: 0.05},
{name: “PENNY”, value: 0.01},
];
const cashInput = document.getElementById(‘cash’);
const changeDue = document.getElementById(‘change-due’);
const purchase = document.getElementById(‘purchase-btn’);

purchase.addEventListener(‘click’, exceptions);
purchase.addEventListener(‘click’, checkCashRegister);

function exceptions() {
if (parseFloat(cashInput.value) < price) {
alert(“Customer does not have enough money to purchase the item”);
} else if (parseFloat(cashInput.value) === price) {
changeDue.textContent = “No change due - customer paid with exact cash”;
} else {
changeDue.textContent = “Status: OPEN”;
}
}

function checkCashRegister() {
let change = parseFloat(cashInput.value - price);
let roundedChange = parseFloat(change.toFixed(2));

let sumCid = 0;
for (let element of cid) {
  sumCid += element[1]
}
let roundedCidSum = parseFloat(sumCid.toFixed(2));

if (roundedCidSum < roundedChange) {
  changeDue.textContent = "Status: INSUFFICIENT_FUNDS"
  return;
}
else if (roundedCidSum === roundedChange) {
  changeDue.textContent = `Status: CLOSED ${denomination}: ${amount}`;
  return;
}

cid = cid.reverse();

for (let i = 0; i < cid.length; i++) {
     let denomination = cid[i][0];
    let amount = cid[i][1];
    let currency = currencyUnit.find(unit => unit.name === denomination);
    let value = 0;
    const currencyValue = parseFloat(Object.values(currencyUnit));
    const currencyName = Object.keys(currencyUnit);

while (roundedChange >= currency.value && amount > 0) {

        roundedChange -= currency.value;

         amount -= currency.value;

    value += currency.value;

    console.log(roundedChange)

    if (roundedChange === 0 ) {
      break;
    }
       }
  if (value > 0) {
    changeDue.textContent += ` ${denomination}: $${value}` 
  }
  
}

}
This is the code like above , the problem is:

@fotis.freskos Please start new thread, including your own code, description what is giving you troubles and what have you tried so far.

1 Like