Why the second product quantity override the first product quantity in java?

Viewed 52

I was trying to develop an order system where it allows users to purchase stationery. Here is how it works:

First, it will show the stationery menu and ask user to enter the id and quantity. the stationery menu and ask user to enter the id and quantity

Then the item selected will be put inside a shopping cart, and if the user wants to buy the same product again, the system will add the quantity together and show the subtotal. shopping cart

However, when user wanted to add another product that is not in the shopping list, it will show this quantity error

The quantity was added up with the previous product, which is not what i wanted. I tried changing the code but it still gave me the same output I would appreciate if anyone can point out my mistakes.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import static java.nio.file.Files.size;
import java.util.Scanner;

public class Order {

    private int product_id;
    private String product_Name;
    private int orderQuantity = 0;
    private double price = 0.0;
    private double subTotal = 0;
    int size = 100;
    Product[] productList = new Product[size];
    int count = 0;
    Order[] orderList = new Order[size];

    public Order() {

    }

    public Order(int product_id, String product_Name, double price, int orderQuantity) {
        this.product_id = product_id;
        this.product_Name = product_Name;
        this.orderQuantity = orderQuantity;
    }

    public Order(int product_id, String product_Name, double price, double subTotal, int orderQuantity) {
        this.product_id = product_id;
        this.product_Name = product_Name;
        this.price = price;
        this.subTotal = subTotal;
        this.orderQuantity = orderQuantity;
    }

    public String getProduct_Name() {
        return product_Name;
    }

    public void setProduct_Name(String product_Name) {
        this.product_Name = product_Name;
    }

    public int getProduct_id() {
        return product_id;
    }

    public void setProduct_id(int product_id) {
        this.product_id = product_id;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getOrderQuantity() {
        return orderQuantity;
    }

    public void setOrderQuantity(int orderQuantity) {
        this.orderQuantity = orderQuantity;
    }

    public Order(double subTotal) {
        this.subTotal = subTotal;
    }

    public double getSubTotal() {
        return subTotal;
    }

    public void setSubTotal(double subTotal) {
        this.subTotal = subTotal;
    }

    public void Menu() {

        System.out.println("Stationaries");
        System.out.println("================");
        System.out.println("ID  Name                Price Quantity");
        System.out.println("=== =================== ===== ========");
        try {
            File product = new File("src/product.txt");
            Scanner order = new Scanner(product);

            while (order.hasNextLine()) {
                String[] data = order.nextLine().split("\\|");
                int product_id = Integer.parseInt(data[0]);
                String product_name = data[1];
                double product_price = Double.parseDouble(data[2]);
                int product_quantity = Integer.parseInt(data[3]);
                productList[count] = new Product(product_id, product_name, product_price, product_quantity);
                count++;
                System.out.printf("%-4d%-20s%-6.2f%-10d\n", product_id, product_name, product_price, product_quantity);
            }

            order.close();
        } catch (FileNotFoundException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }

    public void makeOrder() {
        char yesno;
        boolean check = false;
        int index = 0;
        int count1 = 0;
        int totalprice = 0;
        int finalQuantity = 0;
        boolean exist = false;
        double product_price;
        String product_Name;
        Scanner order = new Scanner(System.in);

        do {
            System.out.print("Enter product ID :");
            int product_Id = order.nextInt(); //1
            product_Name = productList[product_Id - 1].getProduct_name();
            product_price = productList[product_Id - 1].getProduct_price();
            for (int i = 0; i < count; i++) {
                if (product_Id == productList[i].getProduct_id()) {
                    check = true;
                }
            }

            if (check) {
                System.out.print("Enter quantity : ");
                int quantity = order.nextInt();
                orderList[count1] = new Order(product_Id, product_Name, product_price, quantity); //start from 0
                count1++; //move to 1 //total 2 products
            }

            for (int k = 0; k < count1; k++) {
                if (product_Id == orderList[k].getProduct_id()) { //if user enter prod 1, and prod 1 exist in the cart
                    index = k;
                    exist = true;
                    orderList[k].getProduct_id();
                    orderList[k].getOrderQuantity();
                    orderList[k].getPrice();
                    break;
                }
            }

            System.out.println("Shopping Cart");
            System.out.println("================");
            System.out.println("ID  Name                Price Quantity Subtotal");
            System.out.println("=== =================== ===== ======== ========");

            if (exist) {
                finalQuantity += orderList[index].getOrderQuantity();
                orderList[index].setOrderQuantity(finalQuantity); //reset the quantity to the final version
                orderList[index].setSubTotal(orderList[index].getOrderQuantity() * product_price);
                System.out.printf("%-4d%-20s%-6.2f%-10d%-6.2f\n", orderList[index].getProduct_id(), orderList[index].getProduct_Name(), product_price, orderList[index].getOrderQuantity(), orderList[index].getSubTotal());
            } else {
                index++;
                orderList[index].setProduct_id(orderList[index].getProduct_id()); //store at next array
                orderList[index].setOrderQuantity(orderList[index].getOrderQuantity());
                orderList[index].setSubTotal(orderList[index].getOrderQuantity() * product_price);
                System.out.printf("%-4d%-20s%-6.2f%-10d%-6.2f\n", orderList[index].getProduct_id(), orderList[index].getProduct_Name(), product_price, orderList[index].getOrderQuantity(), orderList[index].getSubTotal());
            }
//            } else {
//                index++;
//                orderList[index].setProduct_id(orderList[index].getProduct_id()); //store at next array
//                orderList[index].setOrderQuantity(orderList[index].getOrderQuantity());
//                orderList[index].setSubTotal(orderList[index].getOrderQuantity() * product_price);
//                System.out.printf("%-4d%-20s%-6.2f%-10d%-6.2f\n", orderList[index].getProduct_id(), orderList[index].getProduct_Name(), product_price, orderList[index].getOrderQuantity(), orderList[index].getSubTotal());
//            }

//use later
//            System.out.println("Final Shopping Cart");
//            System.out.println("================");
//            System.out.println("ID  Name                Price Quantity Subtotal");
//            System.out.println("=== =================== ===== ======== ========");
//
//            System.out.printf("%-4d%-20s%-6.2f%-10d%-6.2f\n", orderList[i + 1].getProduct_id(), orderList[i + 1].getProduct_Name(), product_price, orderList[i + 1].getOrderQuantity(), orderList[i + 1].getSubTotal());
//            int num = 0;
//            boolean exist = false;
//            for (int j = 0; j < count1; j++) {
//
//                if (orderList[j].getProduct_id() == num + 1) { //if id is 1
//                    exist = true;
//                    index = j;
//
//                } else {
//                    num++;
//                }
//
//            }
//
//            if (exist) {
//                System.out.println("final quantity=" + (finalQuantity += orderList[index].getOrderQuantity()));
//            }
            System.out.print("Continue Order?(Y|N)");
            yesno = order.next().toUpperCase().charAt(0);
        } while (yesno == 'Y');
    }

}

2 Answers

I think your design is not the best. The below code demonstrates my design. It consists of several classes. Refer to the comments in the below code which explain the design.

An Order contains Items where an Item is a Product together with a quantity.

(Notes after the code.)

package ordering;

import java.math.BigDecimal;

public record Product(int id, String name, BigDecimal price) {

    public boolean equals(Object obj) {
        boolean equal = this == obj;
        if (!equal) {
            if (obj != null) {
                Class<?> thisClass = getClass();
                Class<?> objClass = obj.getClass();
                if (thisClass.equals(objClass)) {
                    Product other = (Product) obj;
                    equal = id == other.id();
                }
            }
        }
        return equal;
    }

    public int hashCode() {
        return id;
    }
}

package ordering;

import java.util.Objects;

/**
 * An item in an order. An item consists of a product and the number of units of that product.
 * 
 * @see ordering.Order
 */
public class Item {

    /** Number of units ordered. */
    private int  amount;

    /** Ordered product. */
    private Product  product;

    /**
     * Creates and returns an instance of this class.
     * 
     * @param prod - product being ordered (cannot be null).
     * @param amt  - number of units of ordered product (must be positive).
     */
    public Item(Product prod, int amt) {
        Objects.requireNonNull(prod, "Null product.");
        if (amt <= 0) {
            throw new IllegalArgumentException("Amount must be positive.");
        }
        product = prod;
        amount = amt;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    public boolean equals(Object obj) {
        boolean equal = this == obj;
        if (!equal) {
            if (obj instanceof Item) {
                Item other = (Item) obj;
                equal = product.equals(other.product);
            }
        }
        return equal;
    }

    public int hashCode() {
        return product.hashCode();
    }

    public String toString() {
        return String.format("%3d\u00D7%s", amount, product);
    }

    /**
     * Adjusts current amount by adding <var>amount</var> to it. Note that <var>amount</var> may be
     * negative.
     * 
     * @param amount - will be added to this instance's current amount.
     * 
     * @throws UnsupportedOperationException  if updated amount is not positive.
     */
    public void updateAmount(int amount) {
        int newAmount = this.amount + amount;
        if (newAmount <= 0) {
            throw new UnsupportedOperationException("Updated amount is not positive.");
        }
        this.amount += amount;
    }
}

package ordering;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * An order consists of a list of items.
 * 
 * @see ordering.Item
 */
public class Order {
    private List<Item> items;

    /**
     * Creates and returns an instance of this class. Creates an order with zero items.
     */
    public Order() {
        items = new ArrayList<>();
    }

    public List<Item> getItems() {
        return new ArrayList<>(items);
    }

    /**
     * Removes <var>item</var> from the list of items in this order. Does nothing if this order
     * does not contain <var>item</var>. A particular {@code Product} appears once only in a single
     * order.
     * 
     * @param item - item to remove.
     */
    public void removeItem(Product item) {
        findItem(item).ifPresent(i -> items.remove(i));
    }

    /**
     * Updates the list of items in this order. If the order already contains <var>item</var> then
     * <var>amount</var> is added to the current amount. Note that <var>amount</var> may be
     * negative.
     * 
     * @param item   - item to update.
     * @param amount - quantity of items.
     * 
     * @throws UnsupportedOperationException  if product amount, after update, is not positive.
     */
    public void updateItem(Product item, int amount) {
        findItem(item).ifPresentOrElse(itm -> itm.updateAmount(amount),
                                       () -> items.add(new Item(item, amount)));
    }

    private Optional<Item> findItem(Product prod) {
        if (prod != null) {
            for (Item item : items) {
                if (prod.equals(item.getProduct())) {
                    return Optional.of(item);
                }
            }
        }
        return Optional.empty();
    }
}

This last class is the actual program.

package ordering;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Ordering {
    private static final char YES = 'Y';
    private static final Scanner STDIN = new Scanner(System.in);
    private static final String DELIMITER = "|";
    private static final String PRODUCTS = "product.txt";

    private static List<Item> stock;
    private static Order order;

    private static boolean checkStock(Product prod, int amount) {
        boolean enough = false;
        for (Item item : stock) {
            Product p = item.getProduct();
            if (p.equals(prod)) {
                int inStock = item.getAmount();
                int newAmount = inStock - amount;
                enough = newAmount >= 0;
                if (enough) {
                    item.setAmount(newAmount);
                }
                else {
                    System.out.printf("Less than %d %s in stock.%n", amount, p.name());
                }
            }
        }
        return enough;
    }

    private static int getAmount() {
        System.out.print("Enter quantity: ");
        return STDIN.nextInt();
    }

    private static Product getProduct() {
        System.out.print("Enter product ID: ");
        int id = STDIN.nextInt();
        Product prod = null;
        for (Item item : stock) {
            Product p = item.getProduct();
            if (p.id() == id) {
                prod = p;
                break;
            }
        }
        if (prod == null) {
            System.out.println("Unknown product.");
        }
        return prod;
    }

    private static void initializeStock() throws IOException {
        Path path = Paths.get(PRODUCTS);
        try (Stream<String> lines = Files.lines(path)) {
            stock = lines.map(Ordering::makeItem)
                         .filter(i -> i != null)
                         .collect(Collectors.toList());
        }
    }

    private static Item makeItem(String line) {
        Item item;
        String[] parts = line.split("\\" + DELIMITER);
        if (parts.length == 4) {
            int id = Integer.parseInt(parts[0]);
            BigDecimal price = new BigDecimal(parts[2]);
            Product prod = new Product(id, parts[1], price);
            item = new Item(prod, Integer.parseInt(parts[3]));
        }
        else {
            item = null;
        }
        return item;
    }

    private static void makeOrder() {
        order = new Order();
        boolean more = true;
        do {
            showMenu();
            Product prod = getProduct();
            if (prod != null) {
                int amount = getAmount();
                if (checkStock(prod, amount)) {
                    try {
                        order.updateItem(prod, amount);
                    }
                    catch (UnsupportedOperationException x) {
                        // Ignore.
                    }
                }
                showOrder();
            }
            STDIN.nextLine();
            System.out.print("Continue Order?(Y|N) ");
            String answer = STDIN.nextLine();
            more = answer.length() > 0 && answer.toUpperCase().charAt(0) == YES;
        } while (more);
    }

    private static void showMenu() {
        System.out.println("Stationaries");
        System.out.println("============");
        System.out.println("ID  Name                Price Quantity");
        System.out.println("=== =================== ===== ========");
        for (Item item : stock) {
            Product p = item.getProduct();
            System.out.printf("%3d %-19s %5.2f %d%n",
                              p.id(),
                              p.name(),
                              p.price().doubleValue(),
                              item.getAmount());
        }
    }

    private static void showOrder() {
        if (order != null) {
            List<Item> items = order.getItems();
            if (items.size() > 0) {
                System.out.println("Your order:");
                System.out.println("ID  Name                Price Quantity Cost");
                System.out.println("=== =================== ===== ======== ======");
                BigDecimal total = new BigDecimal(0);
                for (Item item : order.getItems()) {
                    Product prod = item.getProduct();
                    int amount = item.getAmount();
                    BigDecimal cost = prod.price().multiply(new BigDecimal(amount));
                    total = total.add(cost);
                    System.out.printf("%3d %-19s %5.2f %8d %.2f%n",
                                      prod.id(),
                                      prod.name(),
                                      prod.price().doubleValue(),
                                      amount,
                                      cost);
                }
                System.out.printf("Total: %.2f%n", total);
            }
            else {
                System.out.println("Nothing ordered.");
            }
        }
    }

    public static void main(String[] args) {
        try {
            initializeStock();
            makeOrder();
            showOrder();
            System.out.println("\nGood bye.");
        }
        catch (IOException x) {
            x.printStackTrace();
        }
    }
}
  • It is recommended to use [class] BigDecimal, rather than [primitive] double for handling money.
  • I believe you need at least JDK 9 to run the above code.

Output from a sample run of the above code:

Stationaries
============
ID  Name                Price Quantity
=== =================== ===== ========
  1 rulers               1.00 400
  2 pen                  4.00 700
Enter product ID: 1
Enter quantity: 1
Your order:
ID  Name                Price Quantity Cost
=== =================== ===== ======== ======
  1 rulers               1.00        1 1.00
Total: 1.00
Continue Order?(Y|N) y
Stationaries
============
ID  Name                Price Quantity
=== =================== ===== ========
  1 rulers               1.00 399
  2 pen                  4.00 700
Enter product ID: 1
Enter quantity: 1
Your order:
ID  Name                Price Quantity Cost
=== =================== ===== ======== ======
  1 rulers               1.00        2 2.00
Total: 2.00
Continue Order?(Y|N) y
Stationaries
============
ID  Name                Price Quantity
=== =================== ===== ========
  1 rulers               1.00 398
  2 pen                  4.00 700
Enter product ID: 2
Enter quantity: 1
Your order:
ID  Name                Price Quantity Cost
=== =================== ===== ======== ======
  1 rulers               1.00        2 2.00
  2 pen                  4.00        1 4.00
Total: 6.00
Continue Order?(Y|N) n
Your order:
ID  Name                Price Quantity Cost
=== =================== ===== ======== ======
  1 rulers               1.00        2 2.00
  2 pen                  4.00        1 4.00
Total: 6.00

Good bye.

The code

finalQuantity += orderList[index].getOrderQuantity();

will always increase the value in the variable finalQuantity, which you save later with the code

orderList[index].setOrderQuantity(finalQuantity);

However, you don't set (or reset) the variable finalQuantity to the current quantity of your order/product. That's why you will get the current result of 3 instead of the expected result of 1, because in the previous loop/iteration, that variable was set to 2.

When you want to update the quantity, you need to read the current quantity first and set it in the variable finalQuantity before increasing it by the user input.


On a side note: Your code is structured in an unclear way, which looks (and maybe is) wrong. Your Order class contains different code logic, one for managing one order entry, but also for managing the menu/userinteraction. That makes it weird to have Order[] orderList = new Order[size]; inside the Order class (specially as a field member). It is also not clear if the Order class is in fact for one single order of possible multiple products (in different quantities) or if it has multiple orders (of what?).

You might also want to look into java.util.List<T> and java.util.Map<K,V> to have a container with dynamic size and to save the quantities for each product selected.

Related