Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

My solution does not pass tests #18 or #19 even though when I test it myself, it shows the proper results with the status closed and the resulting denominations.

Your code so far

<!-- file: index.html -->

/* file: script.js */

/* 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/135.0.0.0 Safari/537.36 Edg/135.0.0.0

Challenge Information:

Build a Cash Register Project - Build a Cash Register

Hey there,

Please update the message to include your code. The code was too long to be automatically inserted by the help button.

When you enter a code, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

1 Like
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 UNITS = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];

const table = document.getElementById('drawer');
const cash = document.getElementById('cash');
const changeDue = document.getElementById('change-due');
const cidAmount = document.getElementById('cid-total');
const totalChangeDue = document.getElementById('total-change');

const tenderBtn = document.getElementById('purchase-btn');
const resetBtn = document.getElementById('reset-btn');

const statusOpen = "Status: OPEN";
const statusClosed = "Status: CLOSED";
const statusShort = "Status: INSUFFICIENT_FUNDS";

let registerTotal = 0;

/*VARIABLES INIT*/

initTill(); 

function initTill(){

  table.innerHTML="";

  cid.map(([tender, amount])=>{
    let row = `<tr>
               <td>${tender}</td>
               <td id="tender_${tender}" class="tender">$${amount.toFixed(2)}</td>
               </tr>`;
    table.innerHTML += row;
  });

  registerTotal = cid.reduce((curTotal, [tender,amount] )  => amount*100 + curTotal, 0)/100;

  //Reset TextBoxes
  cidAmount.innerHTML = "TOTAL IN REGISTER: <br>$"+ registerTotal.toFixed(2);
  updateChangeDue(0);
  changeStatus("");

}

function updateChangeDue(changeDue){
  totalChangeDue.innerHTML = "CHANGE DUE: <br>$"+ changeDue;
}

function checkAmount(){

  let change = ((cash.value * 100) - (price * 100));
  let msg = "";

  //Customer didn't give enough money.
  if(change < 0){
    alert("Customer does not have enough money to purchase the item");
  }

  //No change is needed.
  if(change === 0){
    msg = "No change due - customer paid with exact cash";
    changeDue.innerText = msg;
    return;
  } 

  //Change is Needed & Enough Funds.
  if(change > 0){
    totalChangeDue.innerHTML = "TOTAL CHANGE DUE: $" + change / 100;
    getChange(change); 
    return;
  }
 
} 

function changeStatus(status, changeObj = []) {
 
  changeDue.innerText = status; 
  let text = "";
 
  for(let key in changeObj){
     text = ` ${key}: $${changeObj[key]/100}`;
     changeDue.innerText += text;
  }    

}

function getChange(change){

  let currentChange = {};

  let unitFound = "";
  let numUnits = 0;
  let index = 0;
  let moneyUnit = "";
  let changeLeftover = change;
  let total = 0;

  for(let i = UNITS.length - 1; i >= 0;i--){
    if(changeLeftover >= UNITS[i]){   
      //Find Biggest Unit 
      unitFound = UNITS[i];
      index = UNITS.indexOf(unitFound); 

      //How Many Units
      numUnits = Math.floor(changeLeftover / unitFound);

      total = (numUnits * unitFound);

      //If it's not empty, then do this.
      if(cid[i][1] !== 0){

        //Not enough of Unit.
        if(total > Number(cid[i][1] * 100)){ 
          total = cid[i][1] * 100; 
        }
        //Find which Unit
        moneyUnit = cid[i][0];
        currentChange[moneyUnit] = total;
        //Reduce Change
        changeLeftover = changeLeftover - total;    
      }
    } 
  } 

  //If Not Enough Change, then Refuse Sale;
  if(changeLeftover > 0){
      changeStatus(statusShort);
      return;
  }
  
  //Update Register Till
  updateTill(currentChange);
  updateCIDTtl(change);

  //If there is no money left in CID, close register. 
  if(Number(registerTotal) > 0){
    changeStatus(statusOpen, currentChange); 
  }else{
    changeStatus(statusClosed, currentChange);
  }

}

function updateCIDTtl(change = 0){
  let newTotal = (registerTotal - change/100).toFixed(2);
  registerTotal = newTotal;

  cidAmount.innerHTML = "TOTAL IN REGISTER: <br>$"+ registerTotal;
  
}

function updateTill(changeObj){

  let subChange = 0;
  let index, newAmt, oldAmt = 0;
  let unit = "";
  
  for(let i = 0; i < cid.length;i++){

    if( changeObj.hasOwnProperty(cid[i][0]) ){

      unit = cid[i][0];
      oldAmt = cid[i][1];
      subChange = changeObj[unit]/100;
      newAmt = (oldAmt - subChange);
      cid[i][1] = Number(newAmt.toFixed(2));
    }

  }
  updateTable();
}

function updateTable(){

  table.innerHTML = "";
  let cashDrawer = 0;
 
 for(let i = 0; i < 9; i++){
   cashDrawer = cid[i][1];

   let row = `<tr>
              <td>${cid[i][0]}</td>
              <td id="tender_${i}" class="tender">$${cashDrawer}</td>
              </tr>`;
   table.innerHTML += row;
 }

}

tenderBtn.addEventListener("click", checkAmount);
resetBtn.addEventListener("click", initTill);

your code also includes html and css, you have posted your JS twice

1 Like

Can anyone give me a hint as to why tests 18 and 19 do not pass even though when I manually empty the register, it appears to be okay.

I want to do that, please share your html and css

1 Like

I’m sorry, I read that incorrectly. Here’s my HTML.

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8" type="text/html">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <meta name="description" content="Cash Register App">
  <title>Cash Register App</title>

  <!--CSS STYLESHEET-->
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>

<body>

  <div id="window">
      <h1>Cash Register App</h1>
 
    <div id="container">
      
      <div id="box">
        <div id="price-div"></div>
        <input id="cash" type="number" placeholder="$0.00">
        <div id="btn-box">
          <button id="purchase-btn">Amount Tendered</button>
          <button id="reset-btn" >Reset Till</button>
        </div>
      </div>

      <div id="register">
        <table>
          <thead>
            <tr>
              <th>Unit</th>
              <th>TotalAmount</th>
            </tr>
          </thead>
          <tbody id="drawer">
          </tbody>
        </table>
        <div id="change-due">
          <p id="status"> </p>
        </div>

        <div id="cash-tracker">
          <div id="total-change">
          </div>
          <div id="cid-total">
          
          </div>
        </div>

      </div>

    </div><!--End of Container-->

  
  </div><!--End of Window-->

  <script src="script.js" type="text/javascript"></script>
</body>

</html>

Here’s my CSS.

:root{
  --fontColor: #39ff14;
  --desktopColor: #367E81;
  --winColor: #DADADA;
  --secColor: #000B79;
}

*{
  font-family: Verdana;
  font-weight: 400;
  font-style: normal;
  background: var(--desktopColor);
  margin: 0;
  padding: 0;
}

body{
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

#window{
  background-color: rgba(229,229,229, 0.55);
  width: 540px;
  height: 600px;
  border-radius: 5px; 
  padding-top: 10px;
  position: relative;
  border: 1px solid black;
  padding-bottom: 5px;
}

h1{  
  background-color: transparent;
  letter-spacing: 1px;
  font-size: 14px;
  padding-left: 15px;
  padding-bottom: 10px;
}

#container{
  display: flex;
  flex-direction: column;
  border: 1px solid grey;
  align-items: center;
  background: var(--winColor);
  border-radius: 5px;
  margin: 0 auto;
  width: 95%;
  height: 93%;
}

#box{
  padding-top: 20px;
  height: 22%;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

#cash, #price-div{
  width: 80%;
  height: 40%;
  font-size: 24px;
}

label{
  width: 80%;
  text-align: right;
}

#cash{
  background: #000;
  color: var(--fontColor);
  text-align: right;
}

#price-div{
  text-align: center;
  padding-top: 5px;
  background: #fff;
  border: 1px solid grey;
}

::placeholder{
  color: var(--fontColor);
}

#box,label{
  background: inherit;
}
#btn-box{
  display: flex;
  flex-direction: row-reverse;
  justify-content: space-between;
  width: 80%;
  height: 40%;
}

button{
  font-size: 20px;
  height: 100%;
  width: 100%;
  background-color: var(--secColor);
  color: var(--winColor);
  margin-left: auto;
  cursor: pointer;
}

#reset-btn{
  width: 80%;
  background-color: darkgreen; 
  color: white;
}

#register{
  margin-top: 20px;
  width: 400px;
  height: 140px;
  background-color: white;
}

table{
  height: 100%;
  width: 100%;
  text-align: center;
  background-color: var(--winColor);
}

table td:nth-child(1){
  background-color: var(--fontColor);
  color: #000;
  font-weight: 600;
  filter: brightness(.7);
  border: 1px solid;
  width: 45%;
}

table td:nth-child(2){
  background-color: white;
  border: 1px solid darkgrey;
  
}

#change-due{
  width: 100%;
  height: 80px;
  background: #000;
  color: var(--fontColor);
  font-size: 14px;
  margin-top: 10px;
  padding-top:10px;
  text-align: center;
}

#cash-tracker{
  display: flex;
  flex-direction: row;
  font-size: 13px;
  width: 100%;
  height: 40px;
  text-align: center;
  color: var(--fontColor);
}

#total-change, #cid-total{
  background: #000;
  display: flex;
  flex-direction: column;
  width: 100%;
}

p{background:inherit;
  padding: 5px;}

You may want to test, specifically, for test 18. Add this snippet below your code, it does what test 18 does:

console.log("\nTest #18");
price = 19.5;
document.querySelector("#cash").value = 20;
cid = [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];
document.querySelector("#purchase-btn").click();
console.log("actual", document.querySelector("#change-due").innerText);
console.log("expected", "Status: CLOSED PENNY: $0.5");

What I see in the console is this:

Test #18
actual Status: OPEN PENNY: $0.5
expected Status: CLOSED PENNY: $0.5

and for the app

the total in register is not tested, but it doesn’t look like either

If you want to test all the tests in this way, I have it here: cash register test suite.js · GitHub

1 Like

Thank you so much! That helped me to find the the problem.

I made a separate function to initialize the register total, so I just had to move that function to be called when the tender button was clicked.