Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

If I call the functions one by one every test passed, but when trying to call all of them so I can pass the tests some of them fail.

How can I pass the tests? What is the intended way of doing this?

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <input id="cash"/>
  <span id="change-due"></span>
  <button id="purchase-btn">Submit</button>

  <script src="./script.js"></script>
</body>
</html>
/* file: script.js */
let price;
let cid;
const moneyValues = [
    ["ONE HUNDRED", 100],
    ["TWENTY", 20.00],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["NICKEL", 0.05],
    ["PENNY", 0.01]
  ];
const cash = document.getElementById("cash")
const button = document.getElementById("purchase-btn");
const change = document.getElementById("change-due");
const moneyValuesObject = convertArrayToObject(moneyValues);

function sortArray(array){
  return array.sort(function(a, b) {
    return b[1] - a[1];
  });
}

function convertArrayToObject(array){
  return sortArray(array).reduce((acc, [name, value]) => {
    acc[name] = value;
    return acc;
  }, {});
}

function calculateCidTotal(cidObject){
  let total = 0;

  Object.entries(cidObject).forEach((element) => {
    total += element[1];
  })

  return Number(total).toFixed(2);
}

function displayMessage(array, status){
 let message = `Status: ${status}`

 if(status === "INSUFFICIENT_FUNDS"){
   return message;
 }

 array.forEach(element => {
   message += ` ${element[0]}: $${moneyValuesObject[element[0]] * element[1]}`
 })

return message;
}

function finalCheck(price, cash, cid){
  const cidObject = convertArrayToObject(cid);
  const sortedCid = sortArray(moneyValues);
  let changeArray = [];

  if(cash < price) alert("Customer does not have enough money to purchase the item")

  if(cash == price) {
    change.innerHTML = "No change due - customer paid with exact cash"
    return
  }

  let moneyAfterPayment = Number((cash - price).toFixed(2))

  let status = "OPEN";

  sortedCid.forEach((element) => {
    let billCount = 0;
    const changeValue = moneyValuesObject[element[0]];

    if(moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue){
      while (moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue) {
          moneyAfterPayment = Number((moneyAfterPayment - changeValue).toFixed(2));
          cidObject[element[0]] = Number(cidObject[element[0]] - changeValue).toFixed(2);
          billCount++
      }
      
      changeArray.push([element[0], billCount])
    }
  })

  const cidTotal = calculateCidTotal(cidObject);

  if(moneyAfterPayment > 0 || cidTotal < 0){
    status = "INSUFFICIENT_FUNDS"
  }else if(cidTotal == 0.00){
    status = "CLOSED"
  }

  let message = displayMessage(changeArray, status)

  change.innerText = message;
  change.value = message;
}

button.addEventListener("click", () => {
  const cashValue = Number(cash.value);

  finalCheck(20, cashValue, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);

  finalCheck(100, cashValue, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);

   finalCheck(11.95, cashValue, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);

   finalCheck(25, 25, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);

   finalCheck(19.5, cashValue, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]);

  //  finalCheck(19.5, cashValue, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]);
})
/* file: styles.css */

Your browser information:

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

Challenge Information:

Build a Cash Register Project - Build a Cash Register

I haven’t tried this project yet but when I read the instructions I see some important notes that you should be taking into account:

In the script.js file, you have been provided with the price and cid variables. The price variable is the price of the item, and the cid variable is the cash-in-drawer, which is a 2D array listing the available currency in the cash drawer.

The other variable you will need to add is the cash variable, which is the amount of cash provided by the customer for the item, which is provided via an input element on the page.

If you’d like to test your application with different values for price and cid, make sure to declare them with the let keyword so they can be reassigned by our tests.

In your code you have modified the original cid and created money values instead. You must understand that the test is expecting you to get the cid and use the array in it to figure out the returns. So if you are not doing that, your code will not pass.

Here is the original code as given:

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]
];

After all the changes I made my mind wasn’t working properly, I modified the call and almost all of the tests passed except for this one:

When price is less than the value in the #cash element, total cash in drawer cid is equal to change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED" with change due in coins and bills sorted in highest to lowest order.

This is the modified function

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]
];

const moneyValues = [
    ["ONE HUNDRED", 100],
    ["TWENTY", 20.00],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["NICKEL", 0.05],
    ["PENNY", 0.01]
  ];
const cash = document.getElementById("cash")
const button = document.getElementById("purchase-btn");
const change = document.getElementById("change-due");
const moneyValuesObject = convertArrayToObject(moneyValues);

function sortArray(array){
  return array.sort(function(a, b) {
    return b[1] - a[1];
  });
}

function convertArrayToObject(array){
  return sortArray(array).reduce((acc, [name, value]) => {
    acc[name] = value;
    return acc;
  }, {});
}

function calculateCidTotal(cidObject){
  let total = 0;

  Object.entries(cidObject).forEach((element) => {
    total += element[1];
  })

  return Number(total).toFixed(2);
}

function displayMessage(array, status){
 let message = `Status: ${status}`

 if(status === "INSUFFICIENT_FUNDS"){
   return message;
 }

 array.forEach(element => {
   message += ` ${element[0]}: $${moneyValuesObject[element[0]] * element[1]}`
 })

return message;
}

function finalCheck(price, cash, cid){
  const cidObject = convertArrayToObject(cid);
  const sortedCid = sortArray(moneyValues);
  let changeArray = [];

  if(cash < price) alert("Customer does not have enough money to purchase the item")

  if(cash == price) {
    change.innerHTML = "No change due - customer paid with exact cash"
    return
  }

  let moneyAfterPayment = Number((cash - price).toFixed(2))

  let status = "OPEN";

  sortedCid.forEach((element) => {
    let billCount = 0;
    const changeValue = moneyValuesObject[element[0]];

    if(moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue){
      while (moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue) {
          moneyAfterPayment = Number((moneyAfterPayment - changeValue).toFixed(2));
          cidObject[element[0]] = Number(cidObject[element[0]] - changeValue).toFixed(2);
          billCount++
      }
      
      changeArray.push([element[0], billCount])
    }
  })

  const cidTotal = calculateCidTotal(cidObject);

  if(moneyAfterPayment > 0 || cidTotal < 0){
    status = "INSUFFICIENT_FUNDS"
  }else if(cidTotal == 0.00){
    status = "CLOSED"
  }

  let message = displayMessage(changeArray, status)

  change.innerText = message;
  change.value = message;
}

button.addEventListener("click", () => {
  const cashValue = Number(cash.value);

  finalCheck(price, cashValue, cid);
})

Try to spend some time debugging this. Maybe add some logs and modify the cid array so you can see what is happening and where it is happening. If you can’t make progress then show us what you have investigated and the console logs etc.

1 Like

I can’t understand what’s the problem with the final test. If the previous test passed, shouldn’t the last one pass as well?

When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED PENNY: $0.5"
When price is less than the value in the #cash element, total cash in drawer cid is equal to change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED" with change due in coins and bills sorted in highest to lowest order.

i don’t have your code here so I am not sure what I can do from my end to help.
Please share all the code and your logs.

index.html

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <input id="cash"/>
  <span id="change-due"></span>
  <button id="purchase-btn">Submit</button>

  <script src="./script.js"></script>
</body>
</html>

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]
];

const moneyValues = [
    ["ONE HUNDRED", 100],
    ["TWENTY", 20.00],
    ["TEN", 10],
    ["FIVE", 5],
    ["ONE", 1],
    ["QUARTER", 0.25],
    ["DIME", 0.1],
    ["NICKEL", 0.05],
    ["PENNY", 0.01]
  ];
const cash = document.getElementById("cash")
const button = document.getElementById("purchase-btn");
const change = document.getElementById("change-due");
const moneyValuesObject = convertArrayToObject(moneyValues);

function sortArray(array){
  return array.sort(function(a, b) {
    return b[1] - a[1];
  });
}

function convertArrayToObject(array){
  return sortArray(array).reduce((acc, [name, value]) => {
    acc[name] = value;
    return acc;
  }, {});
}

function calculateCidTotal(cidObject){
  let total = 0;

  Object.entries(cidObject).forEach((element) => {
    total += element[1];
  })

  return Number(total).toFixed(2);
}

function displayMessage(array, status){
 let message = `Status: ${status}`

 if(status === "INSUFFICIENT_FUNDS"){
   return message;
 }

 array.forEach(element => {
   message += ` ${element[0]}: $${moneyValuesObject[element[0]] * element[1]}`
 })

return message;
}

function finalCheck(price, cash, cid){
  const cidObject = convertArrayToObject(cid);
  const sortedCid = sortArray(moneyValues);
  let changeArray = [];

  if(cash < price) alert("Customer does not have enough money to purchase the item")

  if(cash == price) {
    change.innerHTML = "No change due - customer paid with exact cash"
    return
  }

  let moneyAfterPayment = Number((cash - price).toFixed(2))

  let status = "OPEN";

  sortedCid.forEach((element) => {
    let billCount = 0;
    const changeValue = moneyValuesObject[element[0]];

    if(moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue){
      while (moneyAfterPayment >= changeValue && cidObject[element[0]] >= changeValue) {
          moneyAfterPayment = Number((moneyAfterPayment - changeValue).toFixed(2));
          cidObject[element[0]] = Number(cidObject[element[0]] - changeValue).toFixed(2);
          billCount++
      }
      
      changeArray.push([element[0], billCount])
    }
  })

  const cidTotal = calculateCidTotal(cidObject);

  if(moneyAfterPayment > 0 || cidTotal < 0){
    status = "INSUFFICIENT_FUNDS"
  }else if(cidTotal == 0.00){
    status = "CLOSED"
  }

  let message = displayMessage(changeArray, status)

  change.innerText = message;
  change.value = message;
}

button.addEventListener("click", () => {
  const cashValue = Number(cash.value);

  finalCheck(price, cashValue, cid);
})

This is the message returned when trying to pass all the tests.

// running tests
When price is less than the value in the #cash element, total cash in drawer cid is equal to change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED" with change due in coins and bills sorted in highest to lowest order.
// tests completed

Just the last test is failing.

okay so I don’t see any console.logs anywhere.
I am not sure why you haven’t tried to log some of the values to try to trace the problem?
When I tried to log some of the main values, I found an issue which then led me to finding the cause of this problem. I want to give you a chance to do the same unless you just want me to tell you what I found?

If you can tell me what values did you use to test the failed test it will be helpful.

Maybe I am not understanding what the test wants from me.

I used 120 as cash and 187 as the price. I then set up the cid to have exactly 13 dollars : 1 ten, 2 single dollars, and 4 quarters. (13 is also the change amount so the cash register should say closed in this test)

After that I added logs to various places so I can see what the code was doing.

How does this work with these values? The last test should return “Status: CLOSED” when the price < cash and the cidTotal after giving the change is 0.

The 120 cash and 187 price values would always return INSSUFICIENT_FUNDS.

Anyway I modified this if condition

 if(moneyAfterPayment > 0 || cidTotal < 0 || price > cash){
    status = "INSUFFICIENT_FUNDS"
  }else if(cidTotal == 0.00){
    status = "CLOSED"
  }

But still the last test wasn’t caused by this.

I am not sure I understand your question.

As you see the price is less than the cash. And the 13 dollars in change is exactly what is in cid.

Modifying code without identifying the cause of the problem will be a frustrating experience.

Why not try adding the logs as I mentioned?

How is the price less than the cash if you said:

I used 120 as cash and 187 as the price.

In this case there is not enough cash to pay for the item.

And even if I switch them, the change is not 13.

I added logs, but as I said before the error is related to the CLOSED case when the cidTotal after giving the change is equal to 0. And if the previous test that tests for “Status CLOSED PENNY: $0.5” works, the last one should pass too.

That is my bad. I thought I was typing 200 but I kept typing 120!

Please select any testcase you like that satisfies the problem!

You threw me off a little, not gonna lie. The cid example you provided was incorrect because the values for each bill should be a multiple of that bill’s value. So the ten bill could never be 1, but 10.

I couldn’t understand what was wrong. I changed the forEach structure to make it work for your example, but it didn’t make any sense for the other tests.

Anyway, I found the problem, and it was pretty stupid because my logic was correct. If one test related to CLOSED cid was passing, the last test that was still related to CLOSED cid should have passed as well.

The problem was that the “CLOSED” message assignment needed a space at the end… "CLOSED ".

The space was present in the final message but I was adding it when listing the bills and values. Even in the test failed log the “CLOSED” message the space is missing.

Thank you for your help.

Sorry I was trying to just communicate that I used one ten , four quarters etc (not the exact values in the cid).

1 Like