Beispiel #1
0
class ItemsHiring(App):
    """ Main application class """

    status_text = StringProperty()

    def on_start(self):
        """ Load items from the CSV file on start """
        source_items = load_items()
        self.item_list = ItemList(source_items)
        self.create_item_buttons()
        self.set_mode(Mode.listing)

    def on_stop(self):
        """ Save items to the CSV file on exit """
        save_items(self.item_list.export_items())

    def build(self):
        """ Build Kivy app from the kv file """
        self.title = "Items Hiring"
        self.root = Builder.load_file('app.kv')
        return self.root

    def create_item_button(self, item, item_index):
        """ Create an item button for a certain item """
        button = ItemButton(text=item.name, hired=item.hired, item_index=item_index)
        button.bind(on_release=self.press_item)
        self.root.ids.itemsGrid.add_widget(button)

    def create_item_buttons(self):
        """ Create the item buttons and add them to the GUI """
        for i, item in enumerate(self.item_list.items):
            self.create_item_button(item, i)

    def clear_selection(self):
        """ Clear any buttons that have been selected """
        for instance in self.root.ids.itemsGrid.children:
            instance.set_selected(False)

    def update_item_buttons(self):
        """ Update colours of item buttons """
        for instance in self.root.ids.itemsGrid.children:
            item = self.item_list.items[instance.item_index]
            instance.hired = item.hired

    def set_mode(self, mode):
        """ Switch between 'listing', 'hiring' and 'returning' modes """
        ids = self.root.ids
        for button in [ids.buttonList, ids.buttonHire, ids.buttonReturn]:
            button.state = 'normal'
        if mode == Mode.listing:
            self.status_text = "Choose action from the left menu, then select items on the right"
            ids.buttonList.state = 'down'
        elif mode == Mode.hiring:
            if self.item_list.count(hired=False) > 0:
                self.status_text = "Select available items to hire"
            else:
                self.status_text = "No items available for hire"
            ids.buttonHire.state = 'down'
        elif mode == Mode.returning:
            if self.item_list.count(hired=True) > 0:
                self.status_text = "Select available items to return"
            else:
                self.status_text = "No items are currently on hire"
            ids.buttonReturn.state = 'down'
        self.clear_selection()
        self.mode = mode

    def show_details(self, item_index):
        """ Display item details in the status bar """
        item = self.item_list.items[item_index]
        status = "out" if item.hired else "in"
        self.status_text = "{}({}), ${:.2f} is {}".format(item.name, item.description, item.price, status)

    def selecting_allowed(self, hired):
        """ Check if item is selectable depending on hired status """
        if self.mode == Mode.hiring and not hired:
            return True
        elif self.mode == Mode.returning and hired:
            return True
        return False

    def show_selection_status(self):
        """ Display selected items in the status bar """
        names = []
        total_price = 0
        for i, button in enumerate(self.root.ids.itemsGrid.children):
            item = self.item_list.items[button.item_index]
            if button.selected:
                names.append(item.name)
                total_price += item.price
        if len(names) == 0:
            names = "no items"
        else:
            names = ", ".join(names)
        if self.mode == Mode.hiring:
            self.status_text = "Hiring: {} for ${:.2f}".format(names, total_price)
        else:
            self.status_text = "Returning: {}".format(names)

    def press_item(self, instance):
        """ Handler for pressing an item button """
        if self.mode == Mode.listing:
            self.show_details(instance.item_index)
            return
        if self.selecting_allowed(instance.hired):
            instance.set_selected(not instance.selected)
        self.show_selection_status()

    def press_list(self):
        """ Handler for pressing the 'List Items' button """
        self.set_mode(Mode.listing)

    def press_hire(self):
        """ Handler for pressing the 'Hire Items' button """
        self.set_mode(Mode.hiring)

    def press_return(self):
        """ Handler for pressing the 'Return Items' button """
        self.set_mode(Mode.returning)

    def press_confirm(self):
        """ Handler for pressing the 'Conrirm' button """
        for button in self.root.ids.itemsGrid.children:
            if not button.selected:
                continue
            item = self.item_list.items[button.item_index]
            if self.mode == Mode.hiring:
                self.item_list.hire_item(button.item_index)
            elif self.mode == Mode.returning:
                self.item_list.return_item(button.item_index)
        self.update_item_buttons()
        self.set_mode(Mode.listing)

    def press_add(self):
        """ Handler for pressing the 'Add New Item' button """
        self.status_text = "Enter details for new item"
        self.root.ids.popup.open()

    def press_save(self, name, description, price):
        """ Handler for pressing the save button in the popup """
        if not name or not description or not price:
            self.status_text = "All fields must be completed"
            return
        try:
            price = float(price)
        except:
            self.status_text = "Price must be a valid number"
            return
        if price <= 0:
            self.status_text = "Price must not be negative or zero"
            return
        self.item_list.add_item(name, description, price, hired=False)
        last_index = len(self.item_list.items) - 1
        item = self.item_list.items[last_index]
        self.create_item_button(item, last_index)
        self.close_popup()

    def close_popup(self):
        """ Close the popup and clear input fields """
        self.root.ids.popup.dismiss()
        self.clear_fields()

    def clear_fields(self):
        """ Clear input fields in the popup """
        self.root.ids.itemName.text = ""
        self.root.ids.itemDescription.text = ""
        self.root.ids.itemPrice.text = ""
Beispiel #2
0
class LibraryController(object):
    """Responsible for all access to objects in library

    Including all items (books, DVDs and journals), and users."""
    MAX_LOANS = 5
    MAX_FINE = 50

    def _log(self, message):
        """Poor man's 'logging'!"""
        if self._verbose:
            print(message)

    def __init__(self, verbose=False):
        """Initialize library, optionally setting verbose mode."""
        self._verbose = verbose
        self._log('Initializing {}'.format(self))
        # Initialize internal lists.
        self._item_list = ItemList()
        self._user_list = UserList()

    def add_item(self, item):
        """Add an item to the library."""
        self._log('Adding item: {}'.format(item))
        self._item_list.add_item(item)

    def add_user(self, user):
        """Add an user to the library."""
        #self._log('Adding user: {}'.format(user))
        self._user_list.add_user(user)

    def is_on_loan(self, item_title):
        """Find out if an item is on load."""
        return self._item_list.is_on_loan(item_title)

    def pay_fine(self, user_id, amount):
        """Pay a find for a user."""
        self._log('Paying fine: {} - {}'.format(user_id, amount))
        self._user_list.pay_fine(user_id, amount)

    def user_checkout(self, user_id, item_title, date=dt.now()):
        """Checkout an item for a user."""
        self._log('User checkout: {} - {}'.format(user_id, item_title))
        if self._user_list.able_to_borrow(user_id, self.MAX_LOANS,
                                          self.MAX_FINE):
            self._log('User {} able to borrow.'.format(user_id))
            item = self._item_list.checkout_item(item_title, date)
            self._user_list.checkout_item(user_id, item, date)
            return True
        else:
            self._log('User {} not able to borrow'.format(user_id))
            return False

    def get_user_fine(self, user_id):
        """Get fines that apply to a user."""
        return self._user_list.get_fine_total(user_id)

    def user_return(self, user_id, item_title):
        """Return an item for a user."""
        self._log('User returning: {} - {}'.format(user_id, item_title))
        self._user_list.return_item(user_id, item_title)
        self._item_list.return_item(item_title)