Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

I have passed every test except for the following:
17. When price is less than the value in the #cash element, total cash in drawer cid is greater than change due, but the individual denomination amounts make it impossible to return needed change, when the #purchase-btn element is clicked, the value in the #change-due element should be “Status: INSUFFICIENT_FUNDS”

I’ve tried testing said criteria manually and it worked with a few combinations. The code for this part are in the lines 130-150 (this is a repost);

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title></title>
		<link rel="stylesheet" href="styles.css">
	</head>
	<body>
		<div class="container">
			<h1>Cash Register Project</h1>
			<div id="change-due">
			</div>
			<label for="cash">Enter cash from customer</label>
			<input type="number" placeholder="Payment" id="cash">
			<button id="purchase-btn"><b>Purchase</b></button>
			<div id="cashRegister">
				<div id="display">
					<div id="display-screen">
						<p id="screen"></p>
					</div>
				</div>
				<div id="neck"></div>
				<div id="bigBox">
					<div id="pads1">
						<div class="pads">
							<div></div>
							<div></div>
							<div></div>
						</div>
						<div class="pads">
							<div></div>
							<div></div>
							<div></div>
						</div>
						<div class="pads">
							<div></div>
							<div></div>
							<div></div>
						</div>
					</div>
					<div id="availability">
						<p><strong>Available change:</strong></p>
						<div id="change"></div>
					</div>
				</div>
				<div id="smallBox">
					<div id="circle"></div>
				</div>
			</div>
		</div>
		<script src="./script.js"></script>
	</body>
</html>
/* file: script.js */
  //-----query the stuff first
  const input = document.getElementById("cash");
  const button = document.getElementById("purchase-btn");
  const screen = document.getElementById("screen");
  const changeListDiv = document.getElementById("change")
  const changeDueDiv = document.getElementById("change-due");
  let toDisplay = {
    status:"",
    'ONE HUNDRED': 0,
    'TWENTY': 0,
    'TEN': 0,
    'FIVE': 0,
    'ONE': 0,
    'QUARTER': 0,
    'DIME': 0,
    'NICKEL': 0,
    'PENNY': 0
  };
  //-----initialize variables
  let price = 3.75;
  let changeMsg = "";

  //remaining change
  let cid = [
    ['PENNY', 1.01],
    ['NICKEL', 0],
    ['DIME', 10],
    ['QUARTER', 0],
    ['ONE', 0],
    ['FIVE', 0],
    ['TEN',0],
    ['TWENTY', 20],
    ['ONE HUNDRED', 100]
  ];

  //determine currency unit's value
  const values = {
    'ONE HUNDRED': 100,
    'TWENTY': 20,
    'TEN': 10,
    'FIVE': 5,
    'ONE': 1,
    'QUARTER': 0.25,
    'DIME': 0.1,
    'NICKEL': 0.05,
    'PENNY': 0.01
  }

  //-----display available information
  screen.innerText = `$${price}`
  const updateAvailableChange = () => {
    changeListDiv.innerHTML = "";
    cid.forEach((item) => {
      const pTag = document.createElement("p");
      pTag.classList.add("change");
      pTag.appendChild(
        document.createTextNode(`${item[0]}: $${formatNumber(item[1])}`)
      );
      changeListDiv.appendChild(pTag);
    });
  };

  //renders the change due
  const updateChangeDueDiv = () => {
    let divMsg = `<p>Status: ${toDisplay.status}</p>`;
    Object.keys(toDisplay).slice(1).forEach((key) => {
      if (toDisplay[key]) {
        divMsg += `<p>${key}: $${formatNumber(toDisplay[key])}</p>`;
      }
    });
    changeDueDiv.innerHTML = divMsg;
  };

  //renders the available change
  updateAvailableChange();

  //utility functions
  function getKeyByValue(object, value) {
    return Object.keys(object).find(key => object[key] === value);
  }

  function findAvailablecid(name){
    return cid.find((item)=>item[0]===name)[1];
  }
  function findIndexcid(name){
    return cid.findIndex((item)=>item[0]===name);
  }
  function formatNumber(num) {
    // Check if the number has decimal places
    if (num % 1 !== 0) {
      return parseFloat(num.toFixed(2)); // Round to 2 decimal places
    }
    return num; // Return as an integer
  }
  //the main function thing

  const insufficientFunds = ()=>{
    toDisplay.status = "INSUFFICIENT_FUNDS"
    updateChangeDueDiv();
  }
  const noDue = ()=>{
    changeDueDiv.innerHTML = "<p>No change due - customer paid with exact cash</p>";
  }

//main function for this project
  const reduceValue = () => {
    toDisplay = {
    status:"",
    'ONE HUNDRED': 0,
    'TWENTY': 0,
    'TEN': 0,
    'FIVE': 0,
    'ONE': 0,
    'QUARTER': 0,
    'DIME': 0,
    'NICKEL': 0,
    'PENNY': 0
  };
    let payment = parseFloat(input.value).toFixed(2);
    let toReturn = parseFloat((payment - price).toFixed(2));
    let maxVal = Infinity;
    let totalChange = 0;
    let totalReturnableChange = 0;

    //calculate total change available
    cid.forEach((item) => totalChange = parseFloat((totalChange + item[1]).toFixed(2)));

    //calculate change that we can actually return (which is the denominations below or equal to the amount we have to return)
    //this code takes the part of cid that is below or equal to what needs to be returned, and then sums it up (to put it simply)
    cid.slice(0,cid.findIndex((item)=>item[0]===Object.keys(values).find((item)=>values[item]===Object.values(values).find((item) => item<=toReturn)))+1).forEach((item)=>totalReturnableChange = parseFloat((totalReturnableChange + item[1]).toFixed(2)));
    //checks if the amount of cash given is enough
    if (toReturn < 0) {
      alert("Customer does not have enough money to purchase the item");
      return;
    } else if (toReturn === 0) {
      noDue();
      return;
    }
    //checks if we have enough change available
    if (toReturn > totalChange) {
      insufficientFunds();
      return;
    }

    //checks if we have enough returnable change available (ik this one makes the other one pointless but its fine)
    if(toReturn>totalReturnableChange){
      insufficientFunds();
      return;
    }
    //keeps looking and reducing as long as there is still a remaining toReturn
    while (toReturn > 0) {
      let reducer = Object.values(values).find((item) => item <= toReturn && item < maxVal);
      // If no reducer is found, insufficient funds
      if (!reducer) {
        insufficientFunds();
        break;
      }

      let reducerName = getKeyByValue(values, reducer);
      // Find available funds for the currency
      let reducerAvailablecid = findAvailablecid(reducerName);
      if (reducerAvailablecid === undefined) {
        maxVal = reducer;
        continue;
      }
      console.log(`Availablecid: ${reducerAvailablecid}`);

      // If there is not enough of this currency, skip to the next one
      if (reducerAvailablecid - reducer < 0) {
        maxVal = reducer;
        continue;
      }

      // Deduct from cid and reduce toReturn
      const index = findIndexcid(reducerName);
      cid[index][1] = parseFloat((cid[index][1] - reducer).toFixed(2));
      toReturn = parseFloat((toReturn - reducer).toFixed(2));

      //updates the amount of this currency (reducer) to display
      toDisplay[reducerName]+=parseFloat(values[reducerName].toFixed(2));

      console.log(`Remaining toReturn: ${toReturn}`);
    }
    totalChange=0;
    cid.forEach((item) => totalChange = parseFloat((totalChange + item[1]).toFixed(2)));

    //checks if there is still change left
    console.log("cid is now " + cid);
    console.log("total change now is: " + totalChange);
    if(totalChange){
      toDisplay.status = "OPEN";
      input.value = "";
    }else{
      toDisplay.status = "CLOSED"
    }
    
    updateChangeDueDiv();
    updateAvailableChange();  

  };


  button.addEventListener("click", reduceValue);
  input.addEventListener('keydown', e => {
    if (e.key === 'Enter') {
  reduceValue();  }
  });
/* file: styles.css */
html, body{
	height:100%;
	width:100%;
	padding: 0;
	background-color: rgba(9, 13, 57, 0.93);
	color:white;
}
body{
	display:flex;
	justify-content: space-evenly;
}

.container{
	width:60%;
	height:100%;
	text-align: center;
	display: flex;
	flex-direction: column;
}
.container >*{
	margin: 10px;
}
#cash{
	margin-top: 0;
	width: 50%;
	margin-left:auto;
	margin-right: auto;
	height: 20px;
}
#purchase-btn{
	width: 30%;
	margin-left:auto;
	margin-right: auto;
	height: 30px;
	transition: all 0.2s;
}
#purchase-btn:hover{
	background-color: orange;
	width: 35%;
}
#purchase-btn:active{
	background-color: red;
}


#cashRegister{
	height: 50%;
	width: 90%;
	margin-left: auto;
	margin-right: auto;
	min-width: 450px;
	max-width: 450px;
}
#cashRegister>*{
	background-color:rgba(99, 43, 117, 0.93);
}
#display {
    margin: 0;
    margin-left: 100px;
    height: 40px;
    width: 200px;
    margin-top: 10px;
    display: flex;
    justify-content: center;
    align-items: center; /* Centers content inside */
}
#display-screen {
	display: flex; /* Enable flexbox */
    justify-content: center; /* Center horizontally */
    align-items: center; /* Center vertically */
    margin: 0; /* Remove auto margins */
    height: 70%;
    width: 95%;
    background-color: black;
}
#screen{
	margin:0;
	color: white;
}

#neck{
	width: 20px;
	height: 60px;
	margin-left: 140px;
}

#bigBox{
	height: 70%;
	min-height: 300px;
	max-height: 300px;
	width: 90%;
	border-top-right-radius: 50px 40%;
	border-top-left-radius: 50px 40%;
	margin-left: 20px;
	display: flex;
}

#pads1{
	background-color: grey;
	height: 100px;
	width: 100px;
	margin:30px;
	margin-right: 0;
	display: flex;
	
}
.pads{
	height: 100%;
	width: auto;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	margin:0;
}
.pads>*{
	background-color: whitesmoke;
	width: 20px;
	height: 20px;
	margin: 10px;
	margin-right: 0px;
}

#smallBox{
	height: 50px;
	margin-top: 15px;
	width: 90%;
	margin-left: 20px;
	display: flex;
	align-items: center;
	justify-content: center;
}
#circle{
	background-color: rgba(9, 13, 57, 0.93);
	height: 30px;
	width: 30px;
	border-radius: 100%;
}


#availability{
	background-color: white;
	height: 70%;
	width: 50%;
	margin-left: 60px;
	margin-top: 80px;
}
.change{
	color:black;
	margin:0;
}
strong{
	margin: 0;
	color: black;
	font-size: 20px;
}
#availability>p{
	margin: 0;
	margin-top: 10px;
	margin-bottom: 5px;
}

Your browser information:

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

Challenge Information:

Build a Cash Register Project - Build a Cash Register

There is errors in your JS, at least in code pen HTML and CSS are good, but you have a noticeable problem with one of the const the screen var should be changed because using the same name as the ID causes a lot of test to fail.

I’ve tried changing the paragraph element’s id name, but it still wont test as passed for the 17th test

The return should be status is all lower case the console log is starting with a capitol S. I really haven’t ran your code yet so give this a try. Even though a lot are passing you could go through them all to make sure.

nope, the instructions tell you to make it in full caps. I’ve found the problem, which is that for the 17th number’s scenario, I still return the change that COULD be given, even though I’m only supposed to display “INSUFFICIENT FUNDS”. Thanks for the help though.

1 Like