Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

Grand rising to Everyone;
I have been working on the cash register project for about three days now. During the time frame, I have been trying seriously hard to complete the project on my own, but I have had some difficulties along the way as well. I have manage to setup a code which passed 17 requirements of the test , and two failed(number 14 & 15 respectively). Can someone please provide me with some clue. Your help will be greatly appreciated .

Your code so far

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

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

const changeDueElement = document.getElementById("change-due");
const cashInputElement = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const priceElement = document.getElementById("price-screen");
const cashInDrawer = document.getElementById("cash-in-drawer")


const layOut = (status, change) => {
  changeDueElement.innerHTML = `<p>Status: ${status}</p>`;
  changeDueElement.innerHTML += change.map(([cashId, cashUnit]) =>`<p>${cashId}: $${cashUnit}`).join("");
}; 


const cashToRegister = () => {
  const cashToCent = Math.round(Number(cashInputElement.value) * 100);
  const priceToCent = Math.round(price * 100);
  if (cashToCent < priceToCent) {
    alert("Customer does not have enough money to purchase the item");
    cashInputElement.value = "";
    return;
  }
  if (cashToCent === priceToCent) {
    changeDueElement.innerHTML =`<p>No change due - customer paid with exact cash</p>`;
    cashInputElement.value = "";
    return;
  }

  let returnCash = cashToCent - priceToCent;
  const cidReverse = [...cid].reverse().map(([cashId, cashUnit]) =>[
    cashId, Math.round(cashUnit * 100)
  ]);

  const cashIds = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1];
  const resultObj = {status: "OPEN", change: []};
  const sumOfCid = cidReverse.reduce((initialCash, [_, cashUnit]) => initialCash + cashUnit, 0);

  if (sumOfCid < returnCash) {
    changeDueElement.innerHTML = `<p>INSUFFICIENT_FUNDS</p>`;
    return;
  }

if (sumOfCid === returnCash) {
  resultObj.status = "CLOSED";
}

for (let n = 0; n <= cidReverse.length; n++) {
  if (returnCash >= cashIds[n] && returnCash > 0) {
    const [cashId, sum] = cidReverse[n];
    const handChange = Math.min(sum, returnCash);
    const counterCheck = Math.floor(handChange / cashIds[n]);
    const sumOfChange = counterCheck * cashIds[n];
    returnCash -= sumOfChange;

    if (counterCheck > 0) {
      resultObj.change.push([cashId, sumOfChange / 100]);
      updateCashId(resultObj.change);
    }
  }
}
if (returnCash > 0) {
  changeDueElement.innerHTML = `<p>Status: INSUFFICIENT_FUNDS</p>`;
  return;
}

if (cashInputElement.value === price && returnChange < cashInputElement.value) {
  changeDueElement.innerHTML = `<p>Status: INSUFFICIENT_FUNDS</p>`;
  return;
}

layOut(resultObj.status, resultObj.change);
updateCashId(resultObj.change);
};

const confirmDueOver = () => {
  if (!cashInputElement.value) {
    return;
  }
  cashToRegister();
};

const updateCashId = (cashId) => {
  const capitalID = {
    PENNY: "Pennies",
    NICKEL: "Nickels",
    DIME: "Dimes",
    QUARTER: "Quarters",
    ONE: "Ones",
    FIVE: "Fives",
    TEN: "Tens",
    TWENTY: "Twenties",
    "ONE HUNDRED": "Hundreds"
  }

  if (cashId) {
    cashId.forEach(([cashCategory, cashValue ]) => {
      const aimArray = cid.find(([cashIds, _]) => cashIds === cashCategory);
      aimArray[1] = (Math.round(aimArray[1] * 100) - Math.round(cashValue * 100)) / 100;
    });
  }
  cashInputElement.value = "";
  priceElement.textContent = `Total: $${price}`;
  cashInDrawer.innerHTML = `<p>Change in drawer:</p>${cid.map(([cashIds, cashUnit]) =>`<p>${capitalID[cashIds]}: $${cashUnit}</p>`).join("")}`;
};

purchaseBtn.addEventListener("click", confirmDueOver);
cashInputElement.addEventListener("keydown", (event) => {
  if (event.key === "Enter") {
    confirmDueOver();
  }
});
![Screenshot 2024-11-15 194732|410x500](upload://cCvi0tPfuGO13ZP5J0pt3qvgMln.jpeg)


Your browser information:

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

Challenge Information:

Build a Cash Register Project - Build a Cash Register

Posting pictures isn’t really helpful. I would talk about what debugging you’ve tried and where you got stuck.

Hi Jeremy;
thanks for your quick reply. The pictures were meant to just show how far I am with the project and the obstacles I am facing at the same time. I got stuck with the number 14 th and 15th test problem, which say:

" * 14. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.01], ["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: INSUFFICIENT_FUNDS"

  • Failed:15. When the price is less than the value in the #cash element and the total cash in the drawer (cid) is insufficient to cover the change due, the purchase should not proceed. When the #purchase-btn is clicked under these conditions, the #change-due element should display "Status: INSUFFICIENT_FUNDS"."

this is exactly what I am showing in the pictures here.

Ok, the picture still isn’t really helpful. Can you talk about how you tried to debug and where you got stuck?

I tried dubbing by rewriting the code and counterchecking for bugs, but seem like I have all in place. As a prove to that, I passed 17 out of the 19 test requirements correctly. This project have been a headache for me about days now but I love it. It challenging and educating at the same time. As you can see below; I built the condition to tackle the problem I am experience now, but it is not working out. I still keep having failed for number 14 and 15:

if (sumOfCid < returnCash) {
    changeDueElement.innerHTML = `<p>INSUFFICIENT_FUNDS</p>`;
    return;
  }

that’s not much debugging…

what happens if you set that cid and price, and you write that cash value in the preview and press the button, what do you get?

Are you suggesting to create new cid and price as stipulated in the requirements?
Can you please explain to me what you mean?

I have reassigned price, cashInputElement, cid, and write a new condition to meet the requirement of number 14 and 15 respectively, but I am stil stuck with the same problem. Can someone please take a quick look at it. Your time will be much appreciated.

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 changeDueElement = document.getElementById("change-due");
const cashInputElement = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const priceElement = document.getElementById("price-screen");
const cashInDrawer = document.getElementById("cash-in-drawer")


const layOut = (status, change) => {
  changeDueElement.innerHTML = `<p>Status: ${status}</p>`;
  changeDueElement.innerHTML += change.map(([cashId, cashUnit]) =>`<p>${cashId}: $${cashUnit}`).join("");
};


const cashRegister = () => {
  const cashToCent = Math.round(Number(cashInputElement.value) * 100);
  const priceToCent = Math.round(price * 100);
  if (cashToCent < priceToCent) {
    alert("Customer does not have enough money to purchase the item");
    cashInputElement.value = "";
    return;
  }
  if (cashToCent === priceToCent) {
    changeDueElement.innerHTML =`<p>No change due - customer paid with exact cash</p>`;
    cashInuptElement.value = "";
    return;
  }

  let returnCash = cashToCent - priceToCent;
  const cidReverse = [...cid].reverse().map(([cashId, cashUnit]) =>[
    cashId, Math.round(cashUnit * 100)
  ]);

  const cashIds = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1];
  const resultObj = {status: "OPEN", change: []};
  const sumOfCid = cidReverse.reduce((initialCash, [_, cashUnit]) => initialCash + cashUnit, 0);

  if (sumOfCid < returnCash) {
    changeDueElement.innerHTML = `<p>INSUFFICIENT_FUNDS</p>`;
    return;
  }

if (sumOfCid === returnCash) {
  resultObj.status = "CLOSED";
}

for (let n = 0; n <= cidReverse.length; n++) {
  if (returnCash >= cashIds[n] && returnCash > 0) {
    const [cashId, sum] = cidReverse[n];
    const handChange = Math.min(sum, returnCash);
    const counterCheck = Math.floor(handChange / cashIds[n]);
    const sumOfChange = counterCheck * cashIds[n];
    returnCash -= sumOfChange;

    if (counterCheck > 0) {
      resultObj.change.push([cashId, sumOfChange / 100]);
      updateCashId(resultObj.change);
    }
  }
}
if (returnCash > 0) {
  changeDueElement.innerHTML = `<p>Status: INSUFFICIENT_FUNDS</p>`;
  return;
}
price = 19.5;
cashInputElement.value = 20;
cid = [
  ["PENNY", 0.01],
  ["NICKEL", 0],
  ["DIME", 0],
  ["QUARTER", 0],
  ["ONE", 0],
  ["FIVE", 0],
  ["TEN", 0],
  ["TWENTY", 0],
  ["ONE HUNDRED", 0]
];

if (cashInDrawer.value < cashInputElement) {
  changeDueElement.innerHTML = `<p>Status: INSUFFICIENT_FUNDS</p>`;
  return;
}

layOut(resultObj.status, resultObj.change);
updateCashId(resultObj.change);
};

const confirmDueOver = () => {
  if (!cashInputElement.value) {
    return;
  }
  cashRegister();
};


const updateCashId = (cashId) => {
  const capitalID = {
    PENNY: "Pennies",
    NICKEL: "Nickels",
    DIME: "Dimes",
    QUARTER: "Quarters",
    ONE: "Ones",
    FIVE: "Fives",
    TEN: "Tens",
    TWENTY: "Twenties",
    "ONE HUNDRED": "Hundreds"
  }

  if (cashId) {
    cashId.forEach(([cashCategory, cashValue ]) => {
      const aimArray = cid.find(([cashIds, _]) => cashIds === cashCategory);
      aimArray[1] = (Math.round(aimArray[1] * 100) - Math.round(cashValue * 100)) / 100;
    });
  }
  cashInputElement.value = "";
  priceElement.textContent = `Total: $${price}`;
  cashInDrawer.innerHTML = `<p>Change in drawer:</p>${cid.map(([cashIds, cashUnit]) =>`<p>${capitalID[cashIds]}: $${cashUnit}</p>`).join("")}`;
};

purchaseBtn.addEventListener("click", confirmDueOver);
cashInputElement.addEventListener("keydown", (event) => {
  if (event.key === "Enter") {
    confirmDueOver();
  }
});

updateCashId();

It’s a little hard to understand your code since you don’t consistently indent.

I wouldn’t manually override in the middle of the function. You should set the global values of the price and drawer as used in the test and see what happens in your code.

To allow for proper debugging you should also share your HTML and CSS please

Greetings;
the attached are the HTML and CSS of my project.

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="eng">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Cash Register</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <header>
      <h1>Cash Register Project</h1>
      <div id="change-due"></div>
      <div class="input-chamber">
        <label for="cash">Enter cash value from customer:</label>
        <input type="number" id="cash" class="cash-input" value="" />
        <button class="check-it-btn" id="purchase-btn">Purchase</button>
      </div>
    </header>
    <main>
      <div class="container">
        <div class="upper-screen-chamber">
          <p id="price-screen" class="items-price">Total: <span><strong>$3.45</strong></span></p>
          <div class="screen-connector"></div>
        </div>
        <div class="upper-register">
          <div class="dial-btn-chamber">
            <button class="dial-btn"><strong>1</strong></button>
            <button class="dial-btn"><strong>2</strong></button>
            <button class="dial-btn"><strong>3</strong></button>
            <button class="dial-btn"><strong>4</strong></button>
            <button class="dial-btn"><strong>5</strong></button>
            <button class="dial-btn"><strong>6</strong></button>
            <button class="dial-btn"><strong>7</strong></button>
            <button class="dial-btn"><strong>8</strong></button>
            <button class="dial-btn"><strong>9</strong></button>
            
          </div>
          <div id="cash-in-drawer" class="cash-in-drawer">
            <p>Cash drawer:</p>
            <p>Penny: <span>$0.01</span></p>
            <p>Nickel: <span>$0.05</span></p>
            <p>Dime: <span>$0.10</span></p>
            <p>Quarter: <span>$0.25</span></p>
            <p>Dollar: <span>$1.00</span></p>
            <p>Five: <span>$5.00</span></p>
            <p>Ten: <span>$10.00</span></p>
            <p>Twenty: <span>$20.00</span></p>
            <p>Hundred: <span>$100.00</span></p>
          </div>
        </div>
        <div class="lower-register">
          <div class="drawer-handle"></div>
        </div>
      </div>
    </main>
    <script src="./script.js"></script>
  </body>
</html>
/*   file:  style.css  */

*,
::before,
::after {
  box-sizing: box-border;
  margin: 0;
  padding: 0;
}

:root {
  --dark-green: #032e03;
  --light-green: #10ad10;
  --black: #000000;
  --orange: #ffa500;
  --dark-orange: #aa7005;
  --white: #ffffff;
}

body {
  background-color: var(--dark-green);
}

header {
  color: var(--white);
  text-align: center;
}

h1 {
  font-size: 2rem;
  margin: 25px 0;
}

main {
  background-color: var(--dark-green);
  padding: 20px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
  gap: 1rem;
  margin: auto;
  justify-items: center;
  width: 50px;
  border-radius: 20px;
}

.dial-btn-chamber {
  display: grid;
  grid-template-columns: 17px 17px 17px;
  grid-template-rows: 17px 17px 17px;
  gap: 9px;
  width: 80px;
  height: 80px;
  border-radius: 20px;;
}

.cash-in-drawer {
  overflow: 100px;
  text-align: left;
  background-color: var(--light-green);
  color: var(--white);
  padding: 12px;
  margin-left: 9px;
  margin-right: 9px;
  margin-bottom: 9px;
  margin-top: 9px;
  border-radius: 20px;
  justify-items: center;
}

.dial-btn {
  background-color: var(--light-green);
  border-style: block;
}

.screen-connector {
  background-color: (--black);
  margin-left: 140px;
  height: 50px;
  width: 40px;
}

.lower-register {
  position: relative;
  background-color: var(--light-green);
  margin: 10px auto;
  width: 342px;
  height: 60px;
  border-radius: 19px 19px 0 0;
  border: 12px solid var(--orange);
}

#price-screen {
  color: var(--white);
  text-align: center;
  height: 28px;
  font-size: 17px;
  margin-top: 15px;
  width: 100px;
  border-radius: 20px;
}
.upper-screen-chamber {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  padding: 4px;
  align-items: center;
  border-radius: 20px;
  border: 5px solid var(--orange);
  margin-left: 40px;
  margin-right: 40px;
  background-color: var(--light-green);
  margin-top: 8px;
  margin-bottom: 8px;
}

.check-it-btn {
  cursor: pointer;
  width: 100px;
  margin: 12px 0 12px 0.5rem;
  color: var(--black);
  background-color: var(--orange);
  background-image: linear-gradient(var(--orange), var(--light-green));
  border-color: var(--black);
  border-width: 4px
}

.drawer-handle {
  margin:16 auto;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  background-color: var(--black)
}
.check-it-btn:hover:enabled {
  background-image: linear-gradient(var(--white), var(--light-green));
};

@media (max-width: 500px) {
  .check-it-btn {
    width: 100px;
  }
}

@media (max-width: 750px) {
  main {
    width: auto;
  }
}




Hey JeremyLT,
thanks once again for your reply. The code are properly indented. Maybe this is due to the pasting of it here. From the HTML, CSS , through the JavaScript, I have all on my screen properly indented. I have unexecuted the overriding of the price and cash in drawer(cid) from inside the function and pushed it out to the global space. I got the result I was expecting from the register app, the test remains failed.

You have a change in indentation here that is inconsistent and makes it hard to tell what is inside and outside of the function

This error is my fault. It came from the copy and paste I did while preparing this post for help. Sorry. As you can see in the attached code blocks, I have upgraded the cid and price , but I am still stuck with two test problems(14 & 15)

let price = 19.5;
let cid = [
  ["PENNY", 0.01],
  ["NICKEL", 0],
  ["DIME", 0],
  ["QUARTER", 0],
  ["ONE", 0],
  ["FIVE", 0],
  ["TEN", 0],
  ["TWENTY", 0],
  ["ONE HUNDRED", 0]
];


const changeDueElement = document.getElementById("change-due");
const cashInputElement = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const priceElement = document.getElementById("price-screen");
const cashInDrawer = document.getElementById("cash-in-drawer")


const layOut = (status, change) => {
  changeDueElement.innerHTML = `<p>Status: ${status}</p>`;
  changeDueElement.innerHTML += change.map(([cashId, cashUnit]) =>`<p>${cashId}: $${cashUnit}`).join("");
};


const cashRegister = () => {
  const cashToCent = Math.round(Number(cashInputElement.value) * 100);
  const priceToCent = Math.round(price * 100);
  if (cashToCent < priceToCent) {
    alert("Customer does not have enough money to purchase the item");
    cashInputElement.value = "";
    return;
  }

  if (cashToCent === priceToCent) {
    changeDueElement.innerHTML =`<p>No change due - customer paid with exact cash</p>`;
    cashInputElement.value = "";
    return;
  }

  let returnCash = cashToCent - priceToCent;
  const cidReverse = [...cid].reverse().map(([cashId, cashUnit]) =>[
    cashId, Math.round(cashUnit * 100)
  ]);

  const cashIds = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1];
  const resultObj = {status: "OPEN", change: []};
  const sumOfCid = cidReverse.reduce((initialCash, [_, cashUnit]) => initialCash + cashUnit, 0);

  if (sumOfCid < returnCash) {
    changeDueElement.innerHTML = `<p>INSUFFICIENT_FUNDS</p>`;
    return;
  }

  if (sumOfCid === returnCash) {
  resultObj.status = "CLOSED";
}

  for (let n = 0; n <= cidReverse.length; n++) {
    if (returnCash >= cashIds[n] && returnCash > 0) {
      const [cashId, sum] = cidReverse[n];
      const handChange = Math.min(sum, returnCash);
      const counterCheck = Math.floor(handChange / cashIds[n]);
      const sumOfChange = counterCheck * cashIds[n];
      returnCash -= sumOfChange;
      
      if (counterCheck > 0) {
        resultObj.change.push([cashId, sumOfChange / 100]);
        updateCashId(resultObj.change);
    }
  }
}
if (returnCash > 0) {
  changeDueElement.innerHTML = `<p>Status: INSUFFICIENT_FUNDS</p>`;
  return;
}
layOut(resultObj.status, resultObj.change);
updateCashId(resultObj.change);
};

const confirmDueOver = () => {
  if (!cashInputElement.value) {
    return;
  }
  cashRegister();
};

const updateCashId = (cashId) => {
  const capitalID = {
    PENNY: "Pennies",
    NICKEL: "Nickels",
    DIME: "Dimes",
    QUARTER: "Quarters",
    ONE: "Ones",
    FIVE: "Fives",
    TEN: "Tens",
    TWENTY: "Twenties",
    "ONE HUNDRED": "Hundreds"
  }

  if (cashId) {
    cashId.forEach(([cashCategory, cashValue ]) => {
      const aimArray = cid.find(([cashIds, _]) => cashIds === cashCategory);
      aimArray[1] = (Math.round(aimArray[1] * 100) - Math.round(cashValue * 100)) / 100;
    });
  }
  cashInputElement.value = "";
  priceElement.textContent = `Total: $${price}`;
  cashInDrawer.innerHTML = `<p>Change in drawer:</p>${cid.map(([cashIds, cashUnit]) =>`<p>${capitalID[cashIds]}: $${cashUnit}</p>`).join("")}`;
};

purchaseBtn.addEventListener("click", confirmDueOver);

cashInputElement.addEventListener("keydown", (event) => {
  if (event.key === "Enter") {
    confirmDueOver();
  }
});

Let’s do some debugging now!

As this is failing:

  1. When price is 19.5 , the value in the #cash element is 20 , cid is [["PENNY", 0.01], ["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: INSUFFICIENT_FUNDS"

let’s add

price = 19.5;
cash.value = 20;
cid = [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];

at the bottom of the editor and click the button

There is INSUFFICIENT_FUNDS in the preview. The requirement is for “Status: INSUFFICIENT_FUNDS” instead. Aren’t you missing something?

Hi ILM,

Thanks so much for the spotlight. I am also sorry for the late reply. I have been having some trouble with my pc for the past days. Now I am go to. All of the test passed and the app is working perfectly now. I left the “status” out, and that was the hold on. Thanks once again :pray: