PROJECT: MediTabs


Introduction

This project portfolio will give you an overview of the documentation, code and ideas I contributed to my team’s project, MediTabs, as the team’s front-end designer. This project was completed as part of an introductory software engineering module in the National University of Singapore (NUS).

Project Overview

MediTabs is a desktop application built with the goal to streamline inventory management in a clinic for pharmacists. As part of the project’s requirements, MediTabs targets users with a preference for command line interactions.

To achieve this goal, we implemented several key features: a warning panel to view urgent issues, an information panel to display medicine information, and data exportation for data analysis.

For this project, I was in-charge of implementing the warning panel and its related commands.

Summary of contributions

This section highlights noteworthy contributions I made to the project’s documentation and source code.

  • Major enhancement: Added a warning panel and related warning commands

    PPP Ui WarningPanel
    Figure 1. MediTabs main interface with the warning panel boxed in red
    • What it does: The warning panel gives users an overview of what medicine batches are expiring/expired and what medicines are low in stock. Thresholds used to determine what is expiring and what is low in stock can be set by the user with simple commands.

    • Justification: Simplifies the process of sieving through an inventory to find expiring/expired medicine batches that need to be disposed of, and medicines that require replenishing. User-defined thresholds add to the user experience.

    • Highlights: This enhancement required an understanding of all major components to render and populate a column in the application’s main interface with the correct lists of items, and to implement complementing commands to change its contents.

  • Minor enhancement: Changed the implementation of Expiry class so that it uses an updated library, (java.time.LocalDate), instead of the deprecated (java.util.Date).

  • Code contributed: [Project Code Dashboard]

  • Other contributions:

    • Source code

      • Changed the application’s colour scheme for a sleeker look: #134

      • Wrote additional tests for existing features to increase test coverage from 88% to 92%: #139, #188

    • Documentation

      • Restructured existing contents of the User Guide: #151

    • Community

      • Pull requests reviewed with suggestions to implementation style: #77, #131

Contributions to the User Guide

The following sections are my contributions to the User Guide. They showcase my ability to write documentation targeting end-users.

Warning Panel

  • The warning panel displays a list of medicines running low on stock and a list of expiring/expired medicine batches.

  • Warnings will be logged in the warnings panel until changes are made to medicines and/or batches displayed, or to the thresholds controlling what is displayed.

  • Image below shows the labelled components of the warning panel:

    WarningPanelLabeled
    Figure 2. Labelled warning panel

Managing the warning panel : warning

Manage the threshold for expiry date and low stock warnings to alter the contents of the warning panel.

Format: warning [e/EXPIRY_THRESHOLD] [q/LOW_STOCK_THRESHOLD] [SHOW]
Provide only one of the optional fields available.
If the thresholds are not set, the default threshold for expiry will be 10 days, and 20 for low stock.
Thresholds set by the user are saved and will be used when the application is launched again.

All thresholds must be positive integers.

  • EXPIRY_THRESHOLD should be number of days before expiry date.

  • LOW_STOCK_THRESHOLD should be in number of stock remaining.

  • SHOW is case insensitive.

Examples:

  • warning e/30
    Medicine batches that have expired or with expiry dates within 30 days to expiry from today will be displayed in the warning panel.

  • warning q/10
    Medicines with a total quantity of less than or equal to 10 will be displayed in the warning panel.

  • warning show
    Current thresholds used for the warning panel will be shown in the result display.

Contributions to the Developer Guide

The following sections are my contributions to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Warning Panel

Current Implementation

The WarningPanel is created as part of the MainWindow, to be displayed in the GUI. Within the panel are two lists, expiring/expired and low in stock, represented by WarningListView objects. The purpose of this feature is to allow the user to view expiring/expired medicine batches and low quantity medicines easily.

The following are some of the operations implemented:

  • Logic#getWarningPanelPredicateAccessor() — Returns a WarningPanelPredicateAccessor. This gives the caller access to all predicates used to filter lists for the warning panel in the current session.

  • WarningPanel#setUpVBox(ObservableList<Medicine>, ObservableList<Medicine>) — Sets up the VBox (vertical box) representing the warning panel by creating WarningListView objects from the ObservableList objects. Each WarningListView is a list to be displayed in the GUI.

Initialising the warning panel

Given below is how the warning panel GUI is initialised on start up.

Step 1. User launches MediTabs, invoking MainWindow#fillInnerPart. The MainWindow class calls Logic#getExpiringMedicinesList, Logic#getLowStockMedicinesList and Logic#getWarningPanelPredicateAccessor to obtain the two ObservableList<Medicine> to be displayed in the warning panel and the predicate accessor used in this session.

Step 2. The WarningPanel is initialised with the objects obtained in Step 1, and constructs a VBox.

Step 3. The WarningPanel self-invokes setUpVBox to populate the VBox with WarningListView objects for display. There will be two WarningListView objects, each initialised with its corresponding ObservableList<Medicine>, a list descriptor and the predicate accessor.

Step 4. The WarningListView configures a ListView<Medicine> object to display elements in the ObservableList<Medicine>. Every ListView<Medicine> cell is populated by a WarningListViewCell object.

Step 5. The WarningListViewCell listens to updates to the ObservableList<Medicine> that would update the medicines/batches to be displayed in the respective list in the warning panel.

The sequence diagram below summarises the above mentioned mechanism.

WarningPanelSequenceDiagram
Figure 3. Sequence diagram illustrating initialisation of the warning panel on start up
Input handling

The basic flow of the warning command in two scenarios are as such:

To change a threshold used by the warning panel

Step 1. The user enters the command warning e/10 to change the threshold for expiring medicine batches.

Step 2. The command is parsed and a WarningCommand object is created with the type and value of the new threshold to be set.

Step 3. The WarningCommand#execute method is invoked.

Step 4. Threshold for expiring medicine batches is changed.

Step 5. The expiring/expired batch list in the warning panel is updated accordingly.

Step 6. The new set of thresholds is shown in the result display box.

To display thresholds currently in use

Step 1. The user enters the command warning show.

Step 2. The command is parsed and a WarningCommand object is created to show current threshold levels.

Step 3. The WarningCommand#execute method is invoked.

Step 4. The current thresholds used are shown in the result display box.

The activity diagram below summarises what happens when the warning command is executed:

WarningCommandActivityDiagram
Figure 4. Activity diagram illustrating what happens when a user executes the warning command

Design Considerations

Aspect: Construction of the lists displayed by the warning panel

Two ObservableLists<Medicine> objects are required, one to display medicine batches expiring soon and the other to display medicines low in stock.

  • Alternative 1 (current choice): Create the ObservableList<Medicine> objects in the ModelManager by filtering the main medicine list, and have MainWindow obtain them via Logic.

    • Pros: Easy to change predicates for filtration, making it possible to set user defined thresholds, thereby improving user experience.

    • Cons: Requires passing the two lists around, from ModelManager to Logic then MainWindow.

  • Alternative 2: Create the ObservableList<Medicine> objects in Ui.

    • Pros: Simple to implement. Filter the main medicine list with the default predicates (i.e. thresholds for expiration and low stock) within WarningPanel.

    • Cons: No separation of concerns. Not possible to set user defined thresholds for either list.

Aspect: Implementation of predicates used for the warning panel
  • Alternative 1 (current choice): Singleton warning panel predicate accessor.

    • Pros: Easy to access and update all warning panel-related predicates.

    • Cons: Must pass the instance of the predicate accessor around to ensure there is only one instance of it at any time.

  • Alternative 2: Save all predicates in the ModelManager.

    • Pros: Easy to implement.

    • Cons: Predicate manipulation from Logic when new thresholds are set violates Dependency Inversion Principle.

Changing warning panel thresholds

  1. Changing the threshold for expiring medicine batches

    1. Prerequisites: Current expiry threshold is 10 days (default). Multiple medicines with batches in the list.

    2. Test case: warning e/0
      Expected: All medicines batches that have expired or are expiring today are shown in the warning panel’s "Expiring Soon/Expired" list. New thresholds are shown in status message.

    3. Test case: warning e/-1
      Expected: No changes to warning panel. Error details shown in the status message.

    4. Other incorrect warning commands to try: warning, warning e/x (where x is not a positive integer), warning {non-whitespace preamble} e/y (where y is a positive integer)
      Expected: Similar to previous.

  2. Changing the threshold for medicines with low stock

    1. Prerequisites: Current low stock threshold is 20 (default). Multiple medicines with non-zero total quantities in the list.

    2. Test case: warning q/0
      Expected: Warning panel’s "Low in Stock" list empties and placeholder "Nothing to show" is displayed. New thresholds are shown in status message.

    3. Test case: warning q/-1
      Expected: No changes to warning panel. Error details shown in the status message.

    4. Other incorrect warning commands to try: warning, warning q/x (where x is not a positive integer), warning {non-whitespace preamble} q/y (where y is a positive integer)
      Expected: Similar to previous.

[Proposed] Data Encryption

Data encryption is likely to be implemented in future versions of the MediTabs if a reasonable implementation is found.

Design Considerations

Aspect: How data encryption is executed
  • Alternative 1: Encrypt the entire inventory.

    • Pros: Easy to implement. Use existing encryption libraries to encrypt the entire inventory.

    • Cons: May have performance issues when encrypting/decrypting large amounts of data.

  • Alternative 2: Only encrypt parts of the inventory user selects.

    • Pros: More efficient in terms of performance (cuts down on encryption/decryption time).

    • Cons: Add encrypt and decrypt command to allow user to choose what needs to be encrypted and decrypted respectively. Need to encrypt/decrypt different chunks of data correctly.

Aspect: Data structure to support data encryption
  • Alternative 1: Save the entire inventory as encrypted data in the database.

    • Pros: Data is secure and not viewable without encryption key.

    • Cons: Implement log in page for decryption of inventory. Require alternative if encryption key is forgotten.

  • Alternative 2: Save encrypted parts of inventory and plaintext in database.

    • Pros: Able to salvage some information if encryption key is lost.

    • Cons: Need to implement packing/unpacking of encrypted data and plaintext during startup/shutdown.