Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

I’m getting several test failures. Really can’t tell why.
From the 7th test on although i test each and they all look good.
My alerts come out with the correct text (tried it with and without “”).
Can someone have a look and help out?
Thanks in advance :sunglasses:

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Cash Register</title>
</head>
<body>
  <h1>Cash Register</h1>
  <label for="price">Price of Item: </label>
  <input type="number" id="price" placeholder="Enter price" step="0.01">
  <br>
  <label for="cash">Cash Provided: </label>
  <input type="number" id="cash" placeholder="Enter cash" step="0.01">
  <br>
  <button id="purchase-btn">Purchase</button>
  <p id="change-due">Change Due</p> 
  <script src="script.js"></script>
</body>
</html>

/* file: script.js */
const priceInput = document.getElementById("price");
const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const changeDueElement = document.getElementById("change-due");


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 currencyUnits = {
  "PENNY": 0.01,
  "NICKEL": 0.05,
  "DIME": 0.1,
  "QUARTER": 0.25,
  "ONE": 1,
  "FIVE": 5,
  "TEN": 10,
  "TWENTY": 20,
  "ONE HUNDRED": 100,
};

const checkCashRegister = (price, cash, cid) => {
  const changeDue = cash - price;
  let totalCid = cid.reduce((sum, denom) => sum + denom[1], 0);
  totalCid = parseFloat(totalCid.toFixed(2));

  if (cash < price) {
    alert("Customer does not have enough money to purchase the item");
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  if (changeDue === 0) {
    updateChangeDue("CLOSED", []);
    return;
  }

  if (totalCid < changeDue) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  const change = [];
  let remainingChange = changeDue;

  cid.reverse().forEach(([unit, amount]) => {
    if (currencyUnits[unit] <= remainingChange && amount > 0) {
      let unitChange = 0;
      while (remainingChange >= currencyUnits[unit] && amount > 0) {
        remainingChange -= currencyUnits[unit];
        remainingChange = parseFloat(remainingChange.toFixed(2));
        amount -= currencyUnits[unit];
        unitChange += currencyUnits[unit];
      }
      change.push([unit, parseFloat(unitChange.toFixed(2))]);
    }
  });

  const totalChange = change.reduce((sum, [, value]) => sum + value, 0);
  if (totalChange < changeDue || remainingChange > 0) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  if (totalChange === totalCid) {
    updateChangeDue("CLOSED", change);
    return;
  }

  updateChangeDue("OPEN", change);
};

const updateChangeDue = (status, change) => {
  if (status === "INSUFFICIENT_FUNDS") {
    changeDueElement.textContent = "Status: INSUFFICIENT_FUNDS";
  } else if (status === "CLOSED") {
    changeDueElement.textContent = `Status: CLOSED ${change.map(([unit, amount]) => `${unit}: $${amount}`).join(" ")}`;
  } else if (status === "OPEN") {
    changeDueElement.textContent = `Status: OPEN ${change.map(([unit, amount]) => `${unit}: $${amount}`).join(" ")}`;
  } else {
    changeDueElement.textContent = "Unexpected status.";
  }
};

purchaseBtn.addEventListener("click", () => {
  const price = parseFloat(priceInput.value);
  const cash = parseFloat(cashInput.value);

  if (isNaN(price) || isNaN(cash) || price <= 0 || cash <= 0) {
    alert("Please enter valid amounts for price and cash provided");
    return;
  }

  // Case 9 & 10: Exact cash
  if (price === cash) {
    changeDueElement.textContent = "No change due - customer paid with exact cash";
    return;
  }

  checkCashRegister(price, cash, cid);
});

/* file: styles.css */

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0

Challenge Information:

Build a Cash Register Project - Build a Cash Register

The first failing test is

. You should have a global variable called price .

please fix this

Done.
Any other idea, still gets stuck on test 7 although i get the alert with the exact text.

const priceInput = document.getElementById("price");
const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const changeDueElement = document.getElementById("change-due");

let price = priceInput;

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 currencyUnits = {
  "PENNY": 0.01,
  "NICKEL": 0.05,
  "DIME": 0.1,
  "QUARTER": 0.25,
  "ONE": 1,
  "FIVE": 5,
  "TEN": 10,
  "TWENTY": 20,
  "ONE HUNDRED": 100,
};

const checkCashRegister = (price, cash) => {
  let changeDue = cash - price;
  let totalCid = Math.round(cid.reduce((sum, [, amount]) => sum + amount, 0) * 100) / 100;

  if (cash < price) {
    alert("Customer does not have enough money to purchase the item");
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  if (changeDue === 0) {
    updateChangeDue("CLOSED", []);
    return;
  }

  if (totalCid < changeDue) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  let change = [];
  let remainingChange = changeDue;
  let updatedCid = cid.slice().reverse().map(([unit, amount]) => [unit, amount]); // Avoid modifying `cid`

  for (let i = 0; i < updatedCid.length; i++) {
    let [unit, amount] = updatedCid[i];
    let unitChange = 0;

    while (remainingChange >= currencyUnits[unit] && amount > 0) {
      remainingChange -= currencyUnits[unit];
      remainingChange = Math.round(remainingChange * 100) / 100;
      amount -= currencyUnits[unit];
      unitChange += currencyUnits[unit];
    }

    if (unitChange > 0) {
      change.push([unit, Math.round(unitChange * 100) / 100]);
      updatedCid[i][1] = amount; // Update `cid`
    }
  }

  let totalChange = Math.round(change.reduce((sum, [, value]) => sum + value, 0) * 100) / 100;

  if (totalChange < changeDue || remainingChange > 0) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  cid = updatedCid.reverse(); // Update `cid` globally

  if (totalChange === totalCid) {
    updateChangeDue("CLOSED", change);
  } else {
    updateChangeDue("OPEN", change);
  }
};

const updateChangeDue = (status, change) => {
  if (status === "INSUFFICIENT_FUNDS") {
    changeDueElement.textContent = "Status: INSUFFICIENT_FUNDS";
  } else if (status === "CLOSED") {
    changeDueElement.textContent = `Status: CLOSED\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else if (status === "OPEN") {
    changeDueElement.textContent = `Status: OPEN\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else {
    changeDueElement.textContent = "Unexpected status.";
  }
};

purchaseBtn.addEventListener("click", () => {
  const price = parseFloat(priceInput.value);
  const cash = parseFloat(cashInput.value);

  if (isNaN(price) || isNaN(cash) || price <= 0 || cash <= 0) {
    alert("Please enter valid amounts for price and cash provided");
    return;
  }

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

  checkCashRegister(price, cash);
});

Add console.log(price) below your declaration so you can see what the value of price is based on your code. Aren’t you missing something?

And what about this? let change = ;

Aren’t you missing something here?
Status: CLOSED\n${change.map(([unit, amount]) => ${unit}: $${amount}).join("\n")}

Look at what your console is telling you. It’s providing valuable information about syntax errors.

Please share any troubleshooting or investigation that you’ve done

Please share any errors, console messages etc. All relevant information.

Console is not returning errors beside the test one, starting from the 7th on…
Set the price variable to an empty array.

let price = [] ;

The change variable is also assigned a empty array like

let change = [];
console.log(change);

I dont get it. What am i doing wrong?

Where did this message come from? I don’t see it in the instructions or tests and I can’t get it to appear when I try your code.

I’ll give you a hint:

The tests run your function a few times back to back. These variables will not be set the second time the function is called.

You should only have 2 global variables:

2. You should have a global variable called price.
3. You should have a global variable called cid.

All other variables should be in the function.

I hope this helps!

Changed like i wrote above to this :

const priceInput = document.getElementById("price");
const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const changeDueElement = document.getElementById("change-due");

let price = [];

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 currencyUnits = {
  "PENNY": 0.01,
  "NICKEL": 0.05,
  "DIME": 0.1,
  "QUARTER": 0.25,
  "ONE": 1,
  "FIVE": 5,
  "TEN": 10,
  "TWENTY": 20,
  "ONE HUNDRED": 100,
};

const checkCashRegister = (price, cash) => {
  let changeDue = cash - price;
  let totalCid = Math.round(cid.reduce((sum, [, amount]) => sum + amount, 0) * 100) / 100;

  if (cash < price) {
    alert("Customer does not have enough money to purchase the item");
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  if (changeDue === 0) {
    updateChangeDue("CLOSED", []);
    return;
  }

  if (totalCid < changeDue) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  let change = [];
console.log(change);
  let remainingChange = changeDue;
  let updatedCid = cid.slice().reverse().map(([unit, amount]) => [unit, amount]); // Avoid modifying `cid`

  for (let i = 0; i < updatedCid.length; i++) {
    let [unit, amount] = updatedCid[i];
    let unitChange = 0;

    while (remainingChange >= currencyUnits[unit] && amount > 0) {
      remainingChange -= currencyUnits[unit];
      remainingChange = Math.round(remainingChange * 100) / 100;
      amount -= currencyUnits[unit];
      unitChange += currencyUnits[unit];
    }

    if (unitChange > 0) {
      change.push([unit, Math.round(unitChange * 100) / 100]);
      updatedCid[i][1] = amount; // Update `cid`
    }
  }

  let totalChange = Math.round(change.reduce((sum, [, value]) => sum + value, 0) * 100) / 100;

  if (totalChange < changeDue || remainingChange > 0) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  cid = updatedCid.reverse(); // Update `cid` globally

  if (totalChange === totalCid) {
    updateChangeDue("CLOSED", change);
  } else {
    updateChangeDue("OPEN", change);
  }
};

const updateChangeDue = (status, change) => {
  if (status === "INSUFFICIENT_FUNDS") {
    changeDueElement.textContent = "Status: INSUFFICIENT_FUNDS";
  } else if (status === "CLOSED") {
    changeDueElement.textContent = `Status: CLOSED\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else if (status === "OPEN") {
    changeDueElement.textContent = `Status: OPEN\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else {
    changeDueElement.textContent = "Unexpected status.";
  }
};

purchaseBtn.addEventListener("click", () => {
  const price = parseFloat(priceInput.value);
  const cash = parseFloat(cashInput.value);

  if (isNaN(price) || isNaN(cash) || price <= 0 || cash <= 0) {
    alert("Please enter valid amounts for price and cash provided");
    return;
  }

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

  checkCashRegister(price, cash);
});

There are only two local variables.
I get the alert on test 7 and i fail anyways.
Where’ s the bug?
Sorry for my noobiness

You should only have 2 global variables: price and cid. All other variables should be in the function.

Have you tried testing anything? Look at the first test:

  1. When price is 20 and the value in the #cash element is 10, an alert should appear with the text "Customer does not have enough money to purchase the item".

When you try this what happens?

i try all test cases and i fail despite doing all actions right.
can you test it?
Do you need the styling css?

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.

How do you set the price variable, and why? The tests will be checking if certain variables are holding certain values. You need to follow the instructions to the letter and not juggle the values around too much.

I’ve been around this exercise for to long.
Do you know how I can reset it and start over?

Noooo ! You’re soooo close!

You just need to simplify your price variable.

Read all the instructions about price and don’t do anything extra or fancy. The instructions do not ask for an HTML price input.

Ok, so i think i get what iḿ doing wrong but iḿ not there yet.
No price input but i think i need to update the html for each test.
Changed both files

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Cash Register</title>
</head>
<body>
  <h1>Cash Register</h1>
    <p>Price of Item: $<span id="price-value"></span></p>
  <br>
  <label for="cash">Cash Provided: </label>
  <input type="number" id="cash" placeholder="Enter cash" step="0.01">
  <br>
  <button id="purchase-btn">Purchase</button>
  <p id="change-due">Change Due</p> <!-- Removed the extra space before the text -->
  <script src="script.js"></script>
</body>
</html>

and

const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const changeDueElement = document.getElementById("change-due");
const priceValue = document.getElementById("price-value");

let price = 11;

function updatePriceDisplay() {
  priceValue.textContent = price;
}

updatePriceDisplay();

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 currencyUnits = {
  "PENNY": 0.01,
  "NICKEL": 0.05,
  "DIME": 0.1,
  "QUARTER": 0.25,
  "ONE": 1,
  "FIVE": 5,
  "TEN": 10,
  "TWENTY": 20,
  "ONE HUNDRED": 100,
};

const checkCashRegister = (price, cash) => {
  let changeDue = cash - price;
  let totalCid = Math.round(cid.reduce((sum, [, amount]) => sum + amount, 0) * 100) / 100;

  if (cash < price) {
    alert("Customer does not have enough money to purchase the item");
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  if (changeDue === 0) {
    updateChangeDue("CLOSED", []);
    return;
  }

  if (totalCid < changeDue) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  let change = [];
  let remainingChange = changeDue;
  let updatedCid = cid.slice().reverse().map(([unit, amount]) => [unit, amount]); 

  for (let i = 0; i < updatedCid.length; i++) {
    let [unit, amount] = updatedCid[i];
    let unitChange = 0;

    while (remainingChange >= currencyUnits[unit] && amount > 0) {
      remainingChange -= currencyUnits[unit];
      remainingChange = Math.round(remainingChange * 100) / 100;
      amount -= currencyUnits[unit];
      unitChange += currencyUnits[unit];
    }

    if (unitChange > 0) {
      change.push([unit, Math.round(unitChange * 100) / 100]);
      updatedCid[i][1] = amount; // Update `cid`
    }
  }

  let totalChange = Math.round(change.reduce((sum, [, value]) => sum + value, 0) * 100) / 100;

  if (totalChange < changeDue || remainingChange > 0) {
    updateChangeDue("INSUFFICIENT_FUNDS", []);
    return;
  }

  cid = updatedCid.reverse(); 

  if (totalChange === totalCid) {
    updateChangeDue("CLOSED", change);
  } else {
    updateChangeDue("OPEN", change);
  }
};

const updateChangeDue = (status, change) => {
  if (status === "INSUFFICIENT_FUNDS") {
    changeDueElement.textContent = "Status: INSUFFICIENT_FUNDS";
  } else if (status === "CLOSED") {
    changeDueElement.textContent = `Status: CLOSED\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else if (status === "OPEN") {
    changeDueElement.textContent = `Status: OPEN\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;
  } else {
    changeDueElement.textContent = "Unexpected status.";
  }
};

purchaseBtn.addEventListener("click", () => {
    const price = parseFloat(priceValue.textContent); 
    const cash = parseFloat(cashInput.value);

  if (isNaN(price) || isNaN(cash) || price <= 0 || cash <= 0) {
    alert("Please enter valid amounts for price and cash provided");
    return;
  }

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

  checkCashRegister(price, cash);
});

Still failing…

just changed the cash variable :

const purchaseBtn = document.getElementById("purchase-btn");
const changeDueElement = document.getElementById("change-due");
const priceValue = document.getElementById("price-value");

let price = 202; 

function updatePriceDisplay() {
  priceValue.textContent = price.toFixed(2); // 
}

updatePriceDisplay();

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 cashInput = document.getElementById("cash");

more tests passing but not all…
try and error

Where in the instructions does it ask for this

  1. When price is less than the value in the #cash element, total cash in drawer cid is greater than the change due, individual denomination amounts allows for returning change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN" with required change due in coins and bills sorted in highest to lowest order.

Look at the string here, "Status: OPEN" That’s the whole string, it ends after the N.

changeDueElement.textContent = `Status: OPEN\n${change.map(([unit, amount]) => `${unit}: $${amount}`).join("\n")}`;

Well…I managed to pass the exercise.
I did it without using any

element on the UI.
When I went back to refactor it failed 1 of the tests…
Anyways I guess I had it more complex than I should.
Done. Thanks for the patience and motivation :smiling_face_with_sunglasses:

1 Like

Have to be really careful when you add things that aren’t specifically in the instructions, because you can’t be sure exactly how the tests will work with it.