Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

I am failing last two tests, despite it working when I try it. For the last test I have tried with different data and it always produces the correct output. I have read a lot of the previous posts on this same issue and not really learned anything which could help, except that there was a bug at one time in the last two tests, which I am assuming has been sorted (or has it?)

Your code so far

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

let price = 19.5;
let cid = [
  ['PENNY', 0.5],
  ['NICKEL', 1.05],
  ['DIME', 0],
  ['QUARTER', 0],
  ['ONE', 0],
  ['FIVE', 0],
  ['TEN', 0],
  ['TWENTY', 0],
  ['ONE HUNDRED',100]
];

// required DOM elements:
const totalPrice = document.getElementById('total');
const cashInDrawer = document.querySelectorAll('li');
const customerCash = document.getElementById('cash');
const purchaseBtn = document.getElementById('purchase-btn');
const changeDueBox = document.getElementById('change-due');
const resetBtn = document.getElementById('reset');

// setting up new array, based on cid, to use for drawer contents :
const currencyList = [
  'Pennies', 'Nickels', 'Dimes', 'Quarters', 'Ones','Fives', 'Tens', 'Twenties', 'Hundreds'
];
let newCid = [];
for (let i = 0; i < cid.length; i++) {
  newCid.push([currencyList[i],cid[i][1]]);  
}

const updateDrawer = () => { // using newCid array to update drawer
  let count = 0;
  cashInDrawer.forEach((item) => {
  item.textContent = `${newCid[count][0]}: $${newCid[count][1]}`
  count++;
});
};
updateDrawer(); // initial drawer setup

const updateArrays = (arr) => { // updating arrays and drawer
  arr = [...arr].reverse();
  for (let i = 0; i <= 8; i++) {
    for (let j = 0; j < arr.length; j++) {      
      if (arr[j][0] === cid[i][0]) {
        cid[i][1] = cid[i][1] - arr[j][1];
        newCid[i][1] = newCid[i][1] - arr[j][1];
      }
    }    
  }
  updateDrawer();    
};

const calculateTotal = (arr) => {// calculating total cash in drawer
  let sum = 0;
  for (let inner of arr) {
    sum+= inner[1];
  }
  sum = parseFloat(sum.toFixed(2));
  return sum;
};

let currentTotal = calculateTotal(cid); // total in drawer

totalPrice.textContent = `Total: $${price}`;

const changeDueMessage = (msg) => { // putting output into 'change due' box
  changeDueBox.style.display = "block";
  changeDueBox.textContent = msg;
}

const createMsg = (status, arr) => { //creates message for change-due element
  let msgStr = `Status: ${status}`;
  for (let item of arr) {
    msgStr += ` ${item[0]}: $${item[1]}`;
  }
  return msgStr;
};

const checkTransaction = () => { // main calculations
  let msg = "";
  let currencyAmounts = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
  const noFunds = "Status: INSUFFICIENT_FUNDS";
  if (!customerCash.value) {
    return;
  }
  let reversedCid = [...cid].reverse();
  const customerMoney = Number(customerCash.value);
  let change = parseFloat((customerMoney - price).toFixed(2));
  let displayMsg = {status: "OPEN", changeArr: []};// object containing output content
  if (customerMoney < price) {
     alert("Customer does not have enough money to purchase the item");
    } else if  (customerMoney === price) {
      msg = "No change due - customer paid with exact cash";
    } else if (currentTotal < change) {
      msg = noFunds;
    } else {
      if (currentTotal === change) {
      displayMsg.status = "CLOSED";
      }
    for (let i = 0; i <= reversedCid.length; i++) {
      if (change >= currencyAmounts[i] && change > 0) {
        let num = 0;
        let amount = reversedCid[i][1];
        while (amount > 0 && change >= currencyAmounts[i]) {
          amount -= currencyAmounts[i];
          change = parseFloat((change - currencyAmounts[i]).toFixed(2));
          num++;
        }
        if (num > 0) {
        displayMsg.changeArr.push([reversedCid[i][0], num * currencyAmounts[i]]);        
        }
      }
    }
    if (change > 0) {
      msg = noFunds;
    } else {
     msg = createMsg(displayMsg.status, displayMsg.changeArr);
    }
    }    
    changeDueMessage(msg);
    msg = "";
    updateArrays(displayMsg.changeArr);
};

const reloadPage = () => {
  location.href = location.href;
};

//event listeners
purchaseBtn.addEventListener('click', checkTransaction);
resetBtn.addEventListener('click', reloadPage);
customerCash.addEventListener('keydown', e => {
  if (e.key === 'Enter') {
    checkTransaction();
  }
}); 

/* 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 Edg/126.0.0.0

Challenge Information:

Build a Cash Register Project - Build a Cash Register

Please begin by moving all global code like this function call into a function that is triggered when we click the purchase button. Otherwise, this function call will only happen once (at the start) and then the tests will set up a series of tests without triggering this code again.

This code also looks like it is in the global scope and needs to move.

I am also concerned about this code. As I recollect, only one button should be in this project. If your logic relies on someone pressing this reset button first, then the tests will fail as they will not trigger it.

My logic does not rely at all on the use of the reset button, but I will remove it. The updateDrawer() function is placed exactly the same as that used in the freecodecamp version, and since the drawer’s content needs to be there before any user clicks on the purchase button, not much use triggering it later! I will look at the moving the global scope variables inside one of the functions.

The drawer contents are the cid variable which is already in the global scope and that is all you should need to know what is there at any moment.

Edit: if none of the code I pointed out is being used for your calculations, and it is only used to set up the external looks of this app, then you can leave it as is as it will not affect the tests.

It is possible that the currentTotal variable is better off in a local scope, which I will look at. The totalPrice.textContent is just setting up the user interface and, as you say, is probably ok as a global variable. As far as you are aware has the issue with the last two tests been sorted? If I present the CSS and HTML code are you able to test it?

hi, yes, the previous issue you spoke of is fixed. (people have been able to pass this project in recent days).

Yes, I can test if I have your code.

OK - it appears that it was just a missing semi-colon that was the issue!! Found it when looking at the code in my text editor (useful when good editors indicate these type of errors). Passed all tests now - thanks for your help.

1 Like

On further thought - I did move the previously indicated global variable inside a function, and I don’t think I tested straight after that, so maybe that was the issue!

1 Like