Supermarket app using OOP I am going in a circle over and over trying to write a "supermarket" application using OOP.

The app should be useful for the employees of a supermarket. The app reads data from a CSV file which looks like this:

name,amount
soap,4
rice,5
bread,10


The supermarket has cashiers and managers. Cashiers should only be able to view the amount for a product. Managers can view but also change an amount. 

Here's the code I came up with:

import pandas

class Data:
    """Creates a pandas dataframe out of a text file"""
    def __init__(self, datafile = "products.txt"):
        self.datafile = datafile

    def get_dataframe(self):
        df = pandas.read_csv("products.txt", index_col = "name")
        return df

    def save_to_csv(self):
        df = pandas.read_csv("products.txt", index_col = "name")
        df.to_csv(self.datafile)
        print(df)


class Product:
    """Represent a product from the dataframe table"""

    def __init__(self, name, dataframe = Data().get_dataframe()):
        self.name = name
        self.dataframe = dataframe

    def get_amount(self):
        """Return the available amount of the product object taken from the dataframe"""
        return self.dataframe.loc[self.name, "amount"]

    def add_amount(self, amount, password):
        """Changes the dataframe by adding an amount to the existing amount"""
        if password == 1234:
            self.dataframe.loc[self.name, "amount"] += amount
            data = Data()
            data.save_to_csv()
            print("Saved")
        else:
            return "You're not a manager"

    def remove_component(self, person):
        """Changes the dataframe by removing an amount from the existing amount"""
        if password == 1234:
            self.dataframe.loc[self.name, amount] -= 1
        else:
            return "You're not a manager"

    def __del__(self):
        """Delete the dataframe from memory when Product is destroyed"""
        del self.dataframe
        Data().save_to_csv()


I think the authentication layer is very poorly implemented here. I simply added a conditional in the add and remove methods. Is there any better way to do the authentication part?

Should I also create Manager and Cashier classes in case I expand the program later. For example, adding info about salaries for managers and cashiers. That would require to have Manager and Cashier objects I guess.

Will the code load many Data objects? Should I use a singleton for the Data object? 

What other design pattern could I have used for this app?
From an OOP design perspective, you've duplicated the sales items. Data is the products, and Products are the products too (hope that makes sense?).

Think back for a second regarding what entities are at work here, and their specific functions. We have:


a manager,  
a cashier,  
a terminal (which the cashier and manager can both use),
and all the products on the store shelves.


Now, both managers and cashiers are of type Person, however Manager can override the Person class with an Edit function (for the products), whereas Cashier would just inherit Person with the in-built View function, correct? (are you with me so far?)
Now, we can be cheeky and assume that the Terminal has Loading and Saving functions - in lieu of the mainframe in the manager's office (typically terminals are just dumb devices and the price editing is handled by the manager with a list of products sent by head office).
Given that the Manager and the Cashier both need to use the Terminal, you would need to have a Logon and Logoff function, correct? That implies a state pattern, which I'll leave you to research.

Now, your question listed the desired functionality:


read/write CSV
Cashiers have view functionality
Managers have view and edit functionality.
Authentication 
Potentially having salaries on managers and cashiers


All these can be achieved in the OOP layout I wrote above. The Authentication component of course would be tied into the Type of which (inherited) Person is logged onto the Terminal (that implies you either need to do some reflection on the logged on user or have an attribute which gives the answer to the terminal).
You also ask: 


  Will the code load many Data objects?


That's hard to say, but it sounds like if you stick with a simple approach, it should keep them to a minimum. Also you ask:


  Should I use a singleton for the Data object?


Given the Terminal is responsible for the product data, if the Terminal loads and saves the product data, I don't think you need to worry about that.

Hope this helps!