1

I am having an issue with comparing the properties of myProduct.setRefno(product.getRefno()), imported from another class along with a description, price and qty. I need to be able to key in a refno and if the reference number exists in the basket container, then I add only the qty rather than all the item details:

Currently program works as follows:

ref1 description1 price1 1(qty)
ref2 description2 price2 1(qty)
ref1 description1 price1 1(qty)

However I would like it as:

ref1 description1 price1 2(qty)
ref2 description2 price2 1(qty)

If it is the same refno then it adds only the qty.

public class Zapper {

    public static void main(String[] args) throws ItemException {
        System.out.println("\n\nThis is Purchases\n\n");

        Products stock=new Products();// Define Variable 
        Products basket=new Products();// Define Variable 
        Purchase product;
        String refno;
        int offer;
        int count;
        int grandtotal;         
        char option;//char variable option

        boolean finished=false;//variable "boolean" set 

        while (!finished) { 
            try {
                option=Console.askOption("\n A)dd P)rint R)emove Q)uit");
                stock.open("stock.lin");
                switch (option) {   
                    case 'A': 
                        product= new Purchase();
                        refno= Console.askString("Enter Ref No:..");
                        product=(Purchase)stock.find(refno);//cast operator 
                        if ( product == null) {
                            System.out.println("Cannot find Ref No");
                        } else {
                            product.print("");
                            Purchase myProduct = new Purchase();
                            myProduct.setRefno(product.getRefno());
                            myProduct.setDescription(product.getDescription());
                            myProduct.setPrice(product.getPrice());
                            myProduct.setQty(1);
                            myProduct.setOffer(product.getOffer());
                            basket.add(myProduct);//add the value of item into Container stock  
                        }
                        break;//end of case statement Add

                    case 'R': 
                        refno= Console.askString("Enter Ref No:..");
                        Product myProduct = new Product();
                        myProduct=(Purchase)basket.find(refno);//cast operator
                        myProduct.setQty(1);
                        if ( myProduct == null)
                            System.out.println("Cannot find Ref No");

                        else {
                            basket.remove(myProduct);
                            basket.print("");   
                        }
                        break;//end of case statement Find

                    case 'P': 
                        basket.print("\nYou have purchased...");
                        break;//end of case statement Print             
                    case 'Q': 
                        finished=true;
                        break;//end of case statement "Q" 
                    case '\0':/*Do Nothing*/
                        break;//end of case statement "Do Nothing"
                    default:    
                        System.out.println("Error: Invalid Option ");
                        break;//end of case statement default
                }
            } catch (ItemException e) {
                System.out.println(e.getMessage());
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }   
        }
        System.out.println("\n\nPurchases Finished \n\n");
    }

}

2 Answers 2

2

You only have to change the add-method in your Products class. Supposing you store your Purchase-objects in a List in your Product class, it could look something like this:

private List<Purchase> products; 

public void add(Purchase product) {
    String refNo = product.getRefno();
    for (Purchase p : this.products) { //for every product
        if (p.getRefno().equals(refNo)) { //if two refNumbers equals
            p.setQty(p.getQty() + product.getQty()); //add the desired quantity
            return; //force method to abort
        }
    }
    this.products.add(product); //otherwise, add the new product
}

Although, I have to say I find some of your class-namings a bit unusual. Remember they should always give a good hint on what they actually represent, eg your Purchase class looks more like a Product. :)

Sign up to request clarification or add additional context in comments.

Comments

0

A lot of your problems will fall away if you use some proper OOP coding techniques.

Lets start with the structure of your class.

public class Zapper {
    public static void main(String[] args) throws ItemException {
        System.out.println("\n\nThis is Purchases\n\n");

        Products stock=new Products();// Define Variable 
        Products basket=new Products();// Define Variable 
        Purchase product;
        String refno;
        int offer;
        int count;
        int grandtotal;         
        char option;//char variable option

        //Do the work...
    }
}

First of all, in no case should main throw an Exception, nevermind a particular one like ItemException. All such things should be handled gracefully by the program. Secondly, you instantiate a bunch of objects that really should be held as member fields within the class, Zapper.

This might be more in tune with what you want:

public class Zapper {
    //These things will stay throughout the program
    private Products stock = new Products();
    private Products basket = new Products();
    private Purchase product;
    private boolean quitSignalReceived = false;
    private Set<Option> options;//A list of keyboard inputs

    public static void main(String[] args) {
        System.out.println("\n\nInitiating Purchase of items\n\n"); //use a proper entrance message to your program

        Zapper zapper = new Zapper();//Create an object! Sets up all class variables on construction.
        zapper.run();//Let a method handle running the program.

        System.out.println("\n\nPurchases Finished \n\n");//Say goodbye!
    }

    public void run() {
        //actually does the work!
    }
}

Now you just need to focus on what run() does. Specifically, it handles your 'main loop':

public void run() {
    boolean finished = false;
    stock.open("stock.lin"); //Should happen every time we enter the run() loop
    while (!finished) {
      option=Console.askOption("\n A)dd P)rint R)emove Q)uit");
      processOption(option);
      if (quitSignalReceived) {
          //Do anything that MUST happen before the program quits.
          finished = true;
      }
    }
}

You've astutely noticed at this point we need to add Options in and process them.

public Zapper() {
   this.options.add(new AddOption());
   this.options.add(new QuitOption());
   //etc.
}

public class Option {
  //Constructor, etc.

  process(String option) {
    for (Option o : options) {
      if (o.getKey.equals(option)) {
        o.process(this);
      }
    }
  }
}

This will naturally require an abstract class, Option, that you subclass:

public abstract class Option {
  public String getKey();//returns the keyboard key associated with this option
  public void process(Zapper z); //actually does what you need the option to do. 
}

Let us consider your 'A' case:

case 'A': 
                    product= new Purchase();
                    refno= Console.askString("Enter Ref No:..");
                    product=(Purchase)stock.find(refno);//cast operator 
                    if ( product == null) {
                        System.out.println("Cannot find Ref No");
                    } else {
                        product.print("");
                        Purchase myProduct = new Purchase();
                        myProduct.setRefno(product.getRefno());
                        myProduct.setDescription(product.getDescription());
                        myProduct.setPrice(product.getPrice());
                        myProduct.setQty(1);
                        myProduct.setOffer(product.getOffer());
                        basket.add(myProduct);//add the value of item into Container stock  
                    }
                    break;//end of case statement Add

First of all, you new() your product, which instantiates an object. Two lines later you set the variable to another object altogether. Secondly, you get that object from a method that does not return a Purchase object, which you should avoid at all cost and at the least encapsulate against future change. Then you have an if switch against null - which is another practice you should always avoid.

In the case of adding a product you want the process method of your Option subclass to look like below.

public void process (Zapper zap) {
    refno= Console.askString("Enter Ref No:..");
    Purchase stockItem;
    bool success = zap.getPurchase(refno, item);
    if ( !success ) {
        System.out.println("Item not in stock.");//Errors should make sense!
    } else {
        zap.addToBasket(stockItem);
    }
}

This requires adding the following methods to Zapper:

public bool findPurchase(String refno, Purchase item) {
    item = this.stock.find(refno);
    if (item == null) { return false; }
}

public void addToBasket(Purchase item) {
    //actually do the work to add it to your purchases.
}

And to Products:

//This method copies the object into a new object and returns it.
public Purchase getPurchaseItem() {
    Purchase myProduct = new Purchase();
    myProduct.setRefno(product.getRefno());
    myProduct.setDescription(product.getDescription());
    myProduct.setPrice(product.getPrice());
    myProduct.setQty(1);
    myProduct.setOffer(product.getOffer());
}

Now, note a tonne of work is done for you if you change this: private Products stock = new Products(); private Products basket = new Products();

To this: private Map stock = new HashMap(); private Map basket = new HashMap();

In this case your call to increment-or-add would look like this:

if (basket.containsKey(item)){
    int quantity = basket.get(item) + 1;
    basket.set(item, quantity);
} else {
    basket.set(item, 1);
}

While this is long it touches on many of the ways you can clean up this code, put responsibility where it belongs and where it is easiest, and solve your problem. If the Map class is insufficent to your needs, you might consider a situation where you have an Item class that comprises an item in stock and a PurchasedItem class that extends that, which is the thing you buy. That's a whole other discussion.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.