:information_source: **Note:** An alternative (arguably, a more OOP) model is given below.
@@ -151,99 +160,196 @@ Classes used by multiple components are in the `seedu.address.commons` package.
--------------------------------------------------------------------------------------------------------------------
-## **Implementation**
+# **Implementation**
This section describes some noteworthy details on how certain features are implemented.
-### \[Proposed\] Undo/redo feature
+## Features
-#### Proposed Implementation
+### Create Doctor feature
-The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+The CreateDoctorCommand is implemented and used to add a new doctor to the MedDict database in address book.
+This command focuses solely on successfully adding a doctor to the system.
-* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history.
+**Example Usage Scenario:**
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+- Step 1: The user launches the application, and the address book is initialized with the current data.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+ - The AddressBookParser will handle the input command when the user types something like :
+ `createDoctor n/Dr Jane Smith p/87654321 e/dr.jane.smith@hospital.com a/456 Elm Street r/physiotherapy`
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
-
+- Step 2: The user executes the create doctor command to add a new doctor to the MedDict database
+in address book.
+ - The `CreateDoctorCommand` is generated by the AddressBookParser
+ and passed to the LogicManager for execution. The `CreateDoctorCommand` checks whether a doctor
+ with the same identity already exists in the MedDict database in address book.
+ If a duplicate is found, the command will not proceed and will return an error message.
+ If no duplicate is found, the doctor will be added to the MedDict database in address book.
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+- Step 3: The command successfully adds the doctor to the MedDict database in address book.
+ - After successfully adding the doctor, the system displays a success message confirming the addition of the new doctor.
-
+The CreatePatientCommand is used to add a new doctor to the MedDict database in address book.
+This command focuses solely on successfully adding a doctor to the system.
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+
-
+### Clear Feature
-
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+The ClearCommand is implemented to reset the MedDict database in the address book by clearing all existing data.
+This command is designed to clear the address book, removing all patients, doctors,
+and related information stored in the system.
-
+**Example Usage Scenario:**
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
+- Step 1: The user launches the application, and the address book is initialized with the current data.
+ - The AddressBookParser will handle the input command when the user types something like:
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather
-than attempting to perform the undo.
+- Step 2: The user executes the clear command to reset the MedDict database.
+ - The ClearCommand is generated by the AddressBookParser and passed to the LogicManager for execution.
+ The ClearCommand then interacts with the model to replace the current address book with a new, empty instance.
-
+- Step 3: The command successfully clears the MedDict database.
+After successfully clearing the address book, the system displays a confirmation message to the user:
-The following sequence diagram shows how an undo operation goes through the `Logic` component:
+ `MedDict has been cleared!`
-
+The ClearCommand feature is a straightforward command used to reset the entire MedDict database in the address book.
+This command does not involve checking for duplicates or specific conditions, as it simply clears all stored data.
-
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
+### \[Proposed\] Sharing Patient Information Feature
+
+#### Proposed Implementation
+
+
+
+**:information_source: SharePatientInfoCommand**
+
+* Parameter 1 : patientId
+
+* Parameter 2 : doctorId
+
+* Format : `SharePatientInfoCommand z/patientId z/doctorId`
+
+* The proposed SharePatientInfoCommand feature will allow secure sharing of patient information between doctors,
+enabling collaborative care while maintaining data privacy.
-Similarly, how an undo operation goes through the `Model` component is shown below:
+**Example Usage Scenario for SharePatientInfoCommand:**
+
+- Step 1: The user initiates the sharePatientInfo command to share specific patient details with another doctor.
+ - The AddressBookParser will handle the input command when the user types something like:
`sharePatientInfo z/1234 z/6789`
-
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+- Step 2: The SharePatientInfoCommand verifies permission and patient existence.
+ - The SharePatientInfoCommand is generated by the AddressBookParser and passed to the LogicManager for execution.
+ The command verifies the doctor’s permission to share the information and checks if the specified patient exists in the system.
+ If the patient exists and sharing is permitted, the command grants access to the specified doctor.
+
+
+- Step 3: The system confirms successful sharing. Upon successful sharing, the system displays a message confirming the action:
+
+ - `Patient information for Patient#XX has been successfully shared with Doctor#YY.`
+
+**Description:**
+The SharePatientInfoCommand feature enables secure sharing of patient information between doctors,
+allowing for collaborative care while maintaining data privacy. This command verifies permissions and patient
+existence before sharing any details, ensuring patient information is handled securely.
+
+**Security Considerations:**
+
+Ensure that patient data access complies with data privacy standards, with permissions and access controls implemented as needed.
+
+**Example Usage Scenario:**
+- Step 1: Doctor A wants to share a patient’s information with Doctor B for coordinated treatment.
+- Step 2: Doctor A executes the command with details, e.g., `sharePatientInfo z/1234 z/6789`.
+AddressBookParser parses the input and creates a SharePatientInfoCommand.
+- Step 3: The command verifies the permission by checking identities of DoctorA and Doctor B
+and grants access, displaying a success message.
+
+**Design Considerations:**
+
+- Aspect: Maintaining Patient Data Privacy in Collaborative Care
+
+- Proposed Choice: Implement access control within SharePatientInfoCommand,
+requiring verification before sharing data.
+
+- **Pros**: Ensures data privacy while allowing collaboration.
+- **Cons**: Adds complexity due to permission management.
+
+
+- **Alternative Approach**: Develop a dedicated sharing module with access logs and permission requests.
+ - **Pros**: Allows a more sophisticated and controlled sharing environment.
+ - **Cons**: Increases system complexity, requiring additional security and privacy checks.
+
+### \[Proposed\] Recording Billing Information Feature
+
+#### Proposed Implementation
+
+
-
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
+**:information_source: RecordBillingInfoCommand**
+
+* Parameter 1: patientId
+* Parameter 2: billingDetails
+* Format: `RecordBillingInfoCommand z/patientId b/billingDetails`
+
+* The proposed RecordBillingInfoCommand feature enables users to record billing information for each session,
+making it easier to manage payments and invoicing.
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+**Example Usage Scenario for RecordBillingInfoCommand:**
+
+- Step 1: The user initiates the RecordBillingInfoCommand to log billing information for a session with a patient.
+The AddressBookParser will handle the input command when the user types something like:
+
+ `recordBillingInfo z/1234 b/Consultation fee: $100, Paid: Yes`
+
-
+- Step 2: The RecordBillingInfoCommand verifies patient existence. The RecordBillingInfoCommand is generated
+by the AddressBookParser and passed to the LogicManager for execution. The command checks if the specified patient exists.
+If the patient is found, the billing information is added to their profile under a “Billing History” section.
+If not, an error message is returned.
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …` command. This is the behavior that most modern desktop applications follow.
-
+- Step 3: The system confirms successful billing record. Upon successful recording, the system displays a message:
-The following activity diagram summarizes what happens when a user executes a new command:
+ `Billing information for Patient#XX has been recorded.`
-

+**Description**:
+The RecordBillingInfoCommand allows doctors to keep track of billing and payment details for each patient session,
+aiding in financial management and invoicing.
-#### Design considerations:
+**Example Usage Scenario**:
+- Step 1: Doctor receives payment from a patient after a session and wants to record it.
-**Aspect: How undo & redo executes:**
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+- Step 2: Doctor executes the command with details, e.g., `recordBillingInfo z/1234 b/Consultation fee: $100, Paid: Yes`.
+AddressBookParser parses the input and generates a RecordBillingInfoCommand.
-* **Alternative 2:** Individual command knows how to undo/redo by
- itself.
- * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted).
- * Cons: We must ensure that the implementation of each individual command are correct.
-_{more aspects and alternatives to be added}_
+- Step 3: The command logs the billing information in the patient's profile, confirming successful record entry.
-### \[Proposed\] Data archiving
+**Design Considerations:**
-_{Explain here how the data archiving feature will be implemented}_
+- Aspect: Storing Billing Information in Patient Profiles
+- Proposed Choice: Add billing entries directly to the patient’s profile.
+- **Pros**: Simple implementation, with easy access to billing records when viewing patient details.
+- **Cons**: Profiles may become cluttered with billing information over time.
+
+- **Alternative Approach**: Store billing information in a separate log or table linked to the patient profile.
+ - **Pros**: Keeps patient profiles focused on medical information while allowing detailed billing history to be retrieved as needed.
+ - **Cons**: Adds complexity in managing a separate billing data structure.
+
--------------------------------------------------------------------------------------------------------------------
## **Documentation, logging, testing, configuration, dev-ops**
@@ -256,6 +362,37 @@ _{Explain here how the data archiving feature will be implemented}_
--------------------------------------------------------------------------------------------------------------------
+## **Appendix: Planned Enhancements**
+
+_Team size: 5_
+
+1. **Ensure that the remarks field integrates well in the application.** Currently the `Edit` remark doesn't work for the remarks of a person and there is no command to delete remarks as well. It seems that there is no way for user to edit the remarks for now. We plan to include the remarks field for the edit command and also design a separate `delete remark` command.
+
+
+2. **Modify the `Find` and `Get` commands**. Currently both find and get commands are only able to search for one word. The commands are unable to differentiate between `Dr A` and `Dr B` as both entries have the same first word. For future changes, we are going to modify the `Find` and `Get` commands such that they will be responsive to an input of strings e.g. `Find Dr A`.
+
+
+3. **Improvement can be done to restrictive name format**. For the name field of a person, currently special characters are not allowed. Moving ahead, we would be showing a warning to the user but still allows for the inclusion of any special characters to a name.
+
+
+4. **Increase the command result box's size**. Currently the command box and command result box are relatively small and it will be very hard for users to view the result of the command that they have entered. Hence, to improve on this, we have planned to increase the size of the command result box and also make it more responsive for better readability.
+
+
+5. **UI improvements for long names, remarks and addresses**. When dealing with long names, remarks and addresses, the app now truncates the value. For future improvement, in order for users to view fully, we would make the UI responsive to long input values.
+
+
+6. **Make the `Find` and `Get` commands more distinct**. It seems that the `Find` and `Get` commands now are quite similar in their functionality. Both could be used to retrieve a person in the model. To improve on this, we will expand on each command.
+
+ E.g. For the `Find` command, the user could not only find based on a segment of names, but also based on phone, email, appointment etc.
+
+
+7. **Improve on the appointment field**. Currently when adding an appointment to patient and doctor, only the starting appointment time is needed. However, in the real life, it would be better if the doctor/user could also specify the end time of the appointment to ensure better planning. Hence, we plan to allow the users to input the end time when adding appointment.
+
+
+8. **Fix the known bug with the sample dataset**. On some devices, there were occasional occurrences of a bug where while trying to add remarks to a person, it would add the remarks to all people in the sample database. This is a bug that could only be replicated at times, upon downloading the .jar file for the first time. As it only affects the sample dataset and the function works fine for user-added patients and doctors, our team has not yet fixed this issue, prioritizing other matters over this as this issue is unlikely to affect the typical and actual use of the application.
+
+--------------------------------------------------------------------------------------------------------------------
+
## **Appendix: Requirements**
### Product scope
@@ -263,42 +400,42 @@ _{Explain here how the data archiving feature will be implemented}_
**Target user profile**:
* Physiotherapists who:
- * Has a significant number of patients to manage
- * Prefers a solution that minimizes data entry and retrieval time
- * Needs quick access to contact details and conditions of patients
- * Needs to monitor and track the progress of recurring / returning patients over a long period of time
- * Prefers typing to mouse interactions and reasonably comfortable using CLI apps
+ * Has a significant number of patients to manage
+ * Prefers a solution that minimizes data entry and retrieval time
+ * Needs quick access to contact details and conditions of patients
+ * Needs to monitor and track the progress of recurring / returning patients over a long period of time
+ * Prefers typing to mouse interactions and reasonably comfortable using CLI apps
**Value proposition**: Provide a more specialised one-stop-for-all medical related information to their patients, schedules, appointments and to keep track of their medical information, progression, medical history etc. The simple CLI app is optimised for physiotherapists’ routine use during consultations, designed for physiotherapists who prioritise speed when accessing and updating patients’ information and details on a regular basis.
### User stories
-Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
-
+Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
+
| Priority | As a … | I want to … | So that I can… |
|----------|---------|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------|
-| `* * *` | Doctor | create a new patient profile | I can record their details and track their progress |
+| `* * *` | Doctor | create a new patient profile | record their details and track their progress |
| `* * *` | Doctor | delete a patient profile | get rid of patient's information that I no longer need / no longer a patient of mine |
| `* * *` | Doctor | add recurring appointments for a patient | manage their treatment schedule efficiently |
| `* * *` | Doctor | update patient details | keep their medical information current |
-| `* * *` | Doctor | add notes to a patient’s record after each session | track their progress over time |
-| `* * *` | Doctor | see which patients have upcoming appointments today | I can prepare in advance |
+| `* * *` | Doctor | add remarks to a patient’s record after each session | track their progress over time |
+| `* * *` | Doctor | see which patients have upcoming appointments today | prepare in advance |
| `* * *` | Doctor | view the history of treatments for a patient | monitor their improvement |
+| `* * *` | Doctor | mark a patient’s session as completed | know which patients have been seen |
| `* * ` | Doctor | filter patients by condition or treatment type | search patients of a particular condition or treatment for more follow-up actions |
-| `* * ` | Doctor | track my own schedule for the week | I can plan my workload |
+| `* * ` | Doctor | track my own schedule for the week | plan my workload |
| `* * ` | Doctor | automatically schedule follow-up appointments for recurring patients | I don’t have to manually book each appointment |
| `* * ` | Doctor | set reminders for follow-up appointments | I don’t miss any important sessions | |
| `* * ` | Doctor | assign different exercises or treatments to a patient | their care plan is personalized |
-| `* * ` | Doctor | mark a patient’s session as completed | I can know which patients have been seen |
-| `* * ` | Doctor | add vital signs data (e.g., blood pressure, heart rate) for a patient | I can monitor their health metrics |
-| `* * ` | Doctor | track patient feedback after each session | I can adjust their treatment plan if needed |
-| `* * ` | Doctor | set goals for a patient’s treatment plan | I can measure their progress against these goals |
-| `* * ` | Doctor | record billing information for each session | I can manage payments and invoicing |
-| `* * ` | Doctor | access a summary of all my patients | I can get an overview of their conditions and treatments |
-| `* * ` | Doctor | view all the sessions a patient has missed | I can follow up with them and arrange for make-up session |
+| `* * ` | Doctor | add vital signs data (e.g., blood pressure, heart rate) for a patient | monitor their health metrics |
+| `* * ` | Doctor | track patient feedback after each session | adjust their treatment plan if needed |
+| `* * ` | Doctor | set goals for a patient’s treatment plan | measure their progress against these goals |
+| `* * ` | Doctor | record billing information for each session | manage payments and invoicing |
+| `* * ` | Doctor | access a summary of all my patients | get an overview of their conditions and treatments |
+| `* * ` | Doctor | view all the sessions a patient has missed | follow up with them and arrange for make-up session |
| `* ` | Doctor | collaborate with other doctors by sharing patient information | we can coordinate care |
-
+
### Use cases
(For all use cases below, the **System** is the `MedDict` and the **Actor** is the `physiotherapist`, unless specified otherwise)
@@ -307,38 +444,38 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
**MSS**
-1. The user searches for the patient in the list by name
-2. MedDict displays all matching patients
-3. The user selects the specific patient profile to delete
-4. The user requests to delete a specific patient in the list
-5. MedDict deletes the patient profile from the system and notifies the user that the profile has been successfully deleted
+1. The user searches for the person in the list by name
+2. MedDict displays all matching persons
+3. The user selects the specific person profile to delete
+4. The user requests to delete a specific person in the list by entering the ID
+5. MedDict deletes the person profile from the system and notifies the user that the profile has been successfully deleted
Use case ends.
**Extensions**
-* 2a: The list of patients is empty.
+* 2a: The list of persons is empty.
- * 2a1. MedDict informs the doctor that no patients are available for deletion
+ * 2a1. MedDict informs the user that no persons are available for deletion
* Use case ends
-* 3a. The given index or patient selection is invalid.
+* 3a. The given index or person selection is invalid.
- * 3a1. MedDict shows an error message indicating that the selected patient profile is invalid or does not exist
+ * 3a1. MedDict shows an error message indicating that the selected person ID is invalid or does not exist
Use case resumes from step 2
-
+
**Use case - UC02: Add Appointment**
**MSS**
1. User requests to make a new appointment
-2. MedDict displays the list of available time slots for appointments
+2. MedDict displays the user's schedule
3. User selects a specific time slot
-4. User searches for the patient by name or the ID
-5. User requests to assign the time slot to a patient
-6. MedDict assigns the selected time slot to the chosen patient and confirms the appointment
+4. User searches for the patient by the ID
+5. User requests to assign the time slot to a person
+6. MedDict assigns the selected time slot to the chosen person and confirms the appointment
Use case ends.
@@ -346,14 +483,14 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
* 2a: No available time slots.
- * 2a1. MedDict notifies the doctor that no time slots are available
- * 2a2. The doctor chooses to wait for a cancellation or manually opens additional time slots
+ * 2a1. MedDict notifies the user that no time slots are available
+ * 2a2. The user chooses to modify the time slot of the appointment
* Use case ends
-* 4a. The selected patient is not found in the system.
+* 4a. The selected person is not found in the system.
- * 4a1. MedDict informs the doctor that the patient is not found
- * 4a2. The doctor is given the option to create a new patient profile or re-enter the patient's name
+ * 4a1. MedDict informs the user that the person is not found
+ * 4a2. The user could create a new person profile or re-enter the person's name
Use case resumes from step 4
@@ -382,7 +519,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
* 3a1. MedDict alerts the user that the selected patient profile is invalid or does not exist
Use case resumes from step 2
-
+
* 4a. The patient’s status has already been marked as completed
* 4a1. MedDict alerts to the user that the appointment has already been marked as completed
@@ -398,19 +535,15 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
4. Command structures should be simple enough for physiotherapists to memorize frequently used operations
5. The searching functionality should not be case-sensitive.
6. The system must be able to handle unexpected errors (e.g., incorrect input, unavailable commands) gracefully by providing clear, actionable error messages
-7. The system should automatically back up patient contact data at least once per day to ensure data integrity. Backups should be encrypted and stored in a secure location
-8. All sensitive contact information, including patient names, phone numbers, and addresses, must be encrypted when stored on disk.
-9. Only authorized users (e.g., licensed physiotherapists) should be able to access or modify patient details.
-10. Authorized users will only have access to the patients under their patient-doctor bond (PDB).
-11. should also be scalable to accommodate larger clinics that may need to store 10,000+ patient records
+7. All sensitive contact information, including patient names, phone numbers, and addresses, must be encrypted when stored on disk.
+8. Only authorized users (e.g., licensed physiotherapists) should be able to access or modify patient details.
+9. should also be scalable to accommodate larger clinics that may need to store 10,000+ patient records
### Glossary
* **Mainstream OS**: Windows, Linux, Unix, MacOS
-* **Patient-Doctor Bond (PDB)**: A relationship between a doctor and a patient where the doctor is assigned to the patient for physiotherapy treatment
-
## **Appendix: Instructions for manual testing**
Given below are instructions to test the app manually.
@@ -420,44 +553,550 @@ testers are expected to do more *exploratory* testing.
+### Command prefixes
+
+| Prefix Constant | Abbreviation |
+|------------------------------|--------------|
+| `PREFIX_NAME` | `n/` |
+| `PREFIX_PHONE` | `p/` |
+| `PREFIX_EMAIL` | `e/` |
+| `PREFIX_ADDRESS` | `a/` |
+| `PREFIX_REMARK` | `r/` |
+| `PREFIX_DATE` | `x/` |
+| `PREFIX_DAY_DATE` | `y/` |
+| `PREFIX_ID` | `z/` |
+
+
### Launch and shutdown
1. Initial launch
- 1. Download the jar file and copy into an empty folder
+ 1. Download the jar file and copy into an empty folder
+
+ 1. Copy or move the .jar file to the folder you want to use as the home folder for your MedDict application. We recommend creating a separate folder for the application as MedDict will create files in the directory it is saved in for storage purposes.
+ 2. Open a command terminal, cd into the folder you put the .jar file in, and use the java -jar addressbook.jar command to run the application.
+ After completing the above, the application should open with a Graphical User Interface (GUI) should appear in a few seconds.
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-1. Saving window preferences
+2. Saving window preferences
- 1. Resize the window to an optimum size. Move the window to a different location. Close the window.
+ 1. Resize the window to an optimum size. Move the window to a different location. Close the window.
- 1. Re-launch the app by double-clicking the jar file.
+ 1. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-1. _{ more test cases … }_
-### Deleting a person
+3. Launch with missing/corrupted data file
+
+ 1. Open the data/addressbook.json file and intentionally introduce invalid JSON syntax.
+ 1. Launch the application.
+ Expected: The app should detect the corrupted data file and display an error message, prompting the user to either reset the data or attempt to recover it. The application should not crash.
+
+
+4. Abrupt shutdown and recovery
+
+ 1. Open the application and make several modifications to doctors and patients list (e.g., add a few entries).
+ 1. Forcefully close the application (e.g., by using Task Manager on Windows or `kill`
command on Mac/Linux).
+ 1. Re-launch the application.
+ Expected: The app should handle the previous abrupt shutdown gracefully. No data corruption should occur and the app should start normally.
+
+### Deleting a person (patient or doctor)
1. Deleting a person while all persons are being shown
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+ 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+
+ 1. Test case: `delete z/1`
+ Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+
+ 1. Test case: `delete z/0`
+ Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+
+ 1. Other incorrect delete commands to try: `delete`, `delete z/x`, `...` (where x is larger than the list size)
+ Expected: Similar to previous.
+
+
+2. Deleting a person when the list is empty
+
+ 1. Prerequisites: Clear the list using the `clear` command.
+
+ 1. Test case: `delete z/x` for any x
+ Expected: No person is deleted. Error message is shown indicating that there are no persons to delete. Status bar remains unchanged.
+
+
+3. Deleting multiple persons consecutively
+
+ 1. Prerequisites: List all persons using the `list` command. Ensure there are at least three persons in the list.
+
+ 1. Test case: `delete z/1`, `delete z/1`, `delete z/1`
+ Expected: The first three persons in the list are deleted consecutively. After each deletion, the status message displays details of the deleted person, and the timestamp in the status bar is updated.
+
+
+4. Deleting with mixed case command
+
+ 1. Test case: `DELETE z/1`
+ Expected: Command is not recognized due to incorrect capitalization. Error message is displayed indicating an unrecognized command. Status bar remains unchanged.
+
+
+5. Deleting a person by name instead of index
+
+ 1. Test case: `delete z/John`
+ Expected: No person is deleted. Error message is shown, indicating that the delete command expects an index, not a name. Status bar remains unchanged.
+
+
+
+### Deleting an appointment
+
+1. Deleting an existing appointment
+
+ 1. Test case: `deleteA z/1234 z/5679 x/2024-12-31 15:23`
+ Expected: The appointment between the doctor with ID 5679 and patient with ID 1234 scheduled on 2024-12-31 15:23 is deleted successfully. A confirmation message "Successfully deleted appointment to a patient" is displayed.
+
+ 2. Test case: `deleteA z/9999 z/5679 x/2024-12-31 15:23` (non-existent patient ID)
+ Expected: No appointment is deleted. An error message "The appointment doesn't exist!" is displayed, as there is no patient with ID 9999.
+
+ 3. Test case: `deleteA z/1234 z/9998 x/2024-12-31 15:23` (non-existent doctor ID)
+ Expected: No appointment is deleted. An error message "The appointment doesn't exist!" is displayed, as there is no doctor with ID 9998.
+
+
+2. Attempting to delete an appointment that does not exist
+
+ 1. Prerequisites: Ensure there is no appointment scheduled between the specified doctor and patient at the specified date and time.
+
+ 2. Test cases: `deleteA z/1234 z/5679 x/2024-12-31 16:00`
+ Expected: No appointment is deleted. An error message "The appointment doesn't exist!" is displayed, as there is no appointment scheduled at 2024-12-31 16:00 between the specified doctor and patient.
+
+
+3. Deleting an appointment with incorrect date format
+
+ 1. Test case: `deleteA z/1234 z/5679 x/31-12-2024 15:23`
+ Expected: No appointment is deleted. An error message is displayed, indicating that the date format is incorrect. The command should specify the correct format (e.g., YYYY-MM-DD HH:MM).
+
+ 2. Test case: `deleteA z/1234 z/5679 x/2024/12/31 15:23`
+ Expected: No appointment is deleted. An error message is displayed, indicating the invalid date format.
+
+
+4. Deleting an appointment without providing required IDs
+
+ 1. Test case: `deleteA x/2024-12-31 15:23` (missing patient and doctor IDs)
+ Expected: No appointment is deleted. An error message is displayed, indicating that both patient and doctor IDs are required.
+
+ 2. Test case: `deleteA z/1234 x/2024-12-31 15:23` (missing doctor ID)
+ Expected: No appointment is deleted. An error message is displayed, indicating that both patient and doctor IDs are required.
+
+
+5. Deleting an appointment with non-numeric IDs
+
+ 1. Test case: `deleteA z/abc z/5679 x/2024-12-31 15:23`
+ Expected: No appointment is deleted. An error message is displayed, indicating that the patient ID must be a numeric value.
+ 2. Test case: `deleteA z/1234 z/xyz x/2024-12-31 15:23`
+ Expected: No appointment is deleted. An error message is displayed, indicating that the doctor ID must be a numeric value.
+
+
+### Creating a patient
+
+1. Creating a new patient with valid details
+ 1. Prerequisites: Ensure the patient's name, phone, email, and address are unique (not already in the system).
+
+ 2. Test cases: `createP n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25`
+ Expected: A new patient profile is created with the specified details. A confirmation message "Successfully created a new patient Patient#
: John Doe" is displayed, where is the unique ID assigned to the new patient.
+
+
+2. Attempting to create a duplicate patient
+ 1. Prerequisites: Ensure a patient profile with the same name, phone, email, and address already exists in the system.
+
+ 2. Test cases: `createP n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25`
+ Expected: No new patient is created. An error message "This patient already exists" is displayed, indicating a duplicate profile.
+
+
+3. Creating a patient with missing required fields
+ 1. Test case: `createP p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25` (missing name)
+ Expected: No patient is created. An error message is displayed, indicating that the name field is required.
+
+ 2. Test case: `createP n/John Doe e/johnd@example.com a/311, Clementi Ave 2, #02-25` (missing phone)
+ Expected: No patient is created. An error message is displayed, indicating that the phone field is required.
+
+ 3. Test case: `createP n/John Doe p/98765432 a/311, Clementi Ave 2, #02-25` (missing email)
+ Expected: No patient is created. An error message is displayed, indicating that the email field is required.
+
+ 4. Test case: `createP n/John Doe p/98765432 e/johnd@example.com` (missing address)
+ Expected: No patient is created. An error message is displayed, indicating that the address field is required.
+
+
+4. Creating multiple patients consecutively
+ 1. Test case: `createP n/Patient A p/91234567 e/patientA@example.com a/123, Baker Street` Followed by: `createP n/Patient B p/81234567 e/patientB@example.com a/456, River Valley Road`
+ Expected: Both patients are created successfully, each with a unique ID. Confirmation messages are displayed for each creation, indicating successful creation of "Patient# : Patient A" and "Patient# : Patient B".
+
+### Creating a doctor
+
+1. Creating a new doctor with valid details
+ 1. Prerequisites: Ensure the doctor's name, phone, email, and address are unique (not already in the system).
+
+ 2. Test case: `createD n/Dr. John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25`
+ Expected: A new doctor profile is created with the specified details. A confirmation message "Successfully created a new doctor Doctor# : Dr. John Doe" is displayed, where is the unique ID assigned to the new doctor.
+
+
+2. Attempting to create a duplicate doctor
+ 1. Prerequisites: Ensure a doctor profile with the same name, phone, email, and address already exists in the system.
+
+ 2. Test case: `createD n/Dr. John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25`
+ Expected: No new doctor is created. An error message "This doctor already exists" is displayed, indicating a duplicate profile.
+
+
+3. Creating a doctor with missing required fields
+
+ 1. Test case: `createD p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25` (missing name)
+ Expected: No doctor is created. An error message is displayed, indicating that the name field is required.
+
+ 2. Test case: `createD n/Dr. John Doe e/johnd@example.com a/311, Clementi Ave 2, #02-25` (missing phone)
+ Expected: No doctor is created. An error message is displayed, indicating that the phone field is required.
+
+ 3. Test case: `createD n/Dr. John Doe p/98765432 a/311, Clementi Ave 2, #02-25` (missing email)
+ Expected: No doctor is created. An error message is displayed, indicating that the email field is required.
+
+ 4. Test case: `createD n/Dr. John Doe p/98765432 e/johnd@example.com` (missing address)
+ Expected: No doctor is created. An error message is displayed, indicating that the address field is required.
+
+
+4. Creating multiple doctors consecutively
+
+ 1. Test case: `createD n/Dr. A p/91234567 e/drA@example.com a/123, Baker Street`
+ Followed by: `createD n/Dr. B p/81234567 e/drB@example.com a/456, River Valley Road`
+ Expected: Both doctors are created successfully, each with a unique ID. Confirmation messages are displayed for each creation, indicating successful creation of "Doctor# : Dr. A" and "Doctor# : Dr. B".
+
+### Adding an appointment
+
+1. Adding a new appointment with valid details
+
+ 1. Prerequisites: Ensure that both the patient and doctor IDs exist in the system and are available at the specified appointment time.
+ 2. Test case: `addA z/1234 z/5679 x/2024-12-31 15:23 r/physiotherapy session`
+ Expected: A new appointment is created successfully for the specified patient and doctor at the specified time. A confirmation message "Successfully added appointment to a patient" is displayed.
+
+
+2. Adding an appointment with unavailable time slot
+
+ 1. Prerequisites: Ensure that either the patient or doctor already has an appointment at the specified time.
- 1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+ 2. Test case: `addA z/1234 z/5679 x/2024-12-31 15:23 r/follow-up`
+ Expected: No appointment is added. An error message "The patient or doctor already has another appointment!" is displayed, indicating that the slot is unavailable.
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
- 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
- Expected: Similar to previous.
+3. Adding an appointment with invalid IDs
-1. _{ more test cases … }_
+ 1. Prerequisites: Use non-existent patient or doctor IDs.
+
+ 2. Test case: `addA z/9999 z/5679 x/2024-12-31 15:23 r/consultation` (non-existent patient ID)
+ Expected: No appointment is added. An error message "The doctor or the patient ID that you have entered doesn't exist. Please enter again!" is displayed.
+
+ 3. Test case: `addA z/1234 z/9998 x/2024-12-31 15:23 r/consultation` (non-existent doctor ID)
+ Expected: No appointment is added. The same error message as above is displayed.
+
+
+4. Adding an appointment with missing required fields
+
+ 1. Test case: `addA z/1234 z/5679 r/check-up` (missing date)
+ Expected: No appointment is added. An error message is displayed indicating that the date field is required.
+
+ 2. Test case: `addA z/1234 x/2024-12-31 15:23 r/check-up` (missing doctor ID)
+ Expected: No appointment is added. An error message is displayed indicating that the doctor ID field is required.
+
+
+5. Adding an appointment with invalid date format
+
+ 1. Test case: `addA z/1234 z/5679 x/31-12-2024 15:23 r/check-up` (incorrect date format)
+ Expected: No appointment is added. An error message is displayed indicating the date format should be YYYY-MM-DD HH:MM.
+
+
+6. Adding multiple appointments consecutively
+
+ 1. Test case: `addA z/1234 z/5679 x/2024-12-31 14:00 r/check-up`
+ Followed by: `addA z/1234 z/5679 x/2024-12-31 16:00 r/follow-up`
+ Expected: Both appointments are added successfully, each at the specified time. A confirmation message is displayed for each appointment, indicating successful addition.
+
+
+
+### Adding a remark
+
+1. Adding remarks with valid patient ID
+
+ 1. Prerequisites: Ensure that the patient with the specified ID exists in the system.
+
+ 2. Test case: `addR z/1234 r/Much better than previous appointment.`
+ Expected: The remark is successfully added to the patient with ID 1234. A confirmation message is displayed: "Successfully added remarks: Much better than previous appointment to patient of ID: 1234."
+
+
+2. Adding multiple remarks to the same patient consecutively
+
+ 1. Prerequisites: Ensure that the patient with the specified ID exists in the system.
+
+ 2. Test case: `addR z/1234 r/Needs more rest.` followed by `addR z/1234 r/Monitor blood pressure.`
+ Expected: Both remarks are added to the patient with ID 1234, with each remark appended to the existing ones. A confirmation message is displayed for each addition.
+
+
+3. Adding remarks with non-existent patient ID
+
+ 1. Test case: `addR z/9999 r/Condition improving.` (where patient ID 9999 does not exist)
+ Expected: No remarks are added. An error message "Unable to add remarks! Check the ID entered!" is displayed, indicating that the patient ID is invalid.
+
+
+4. Adding empty remarks
+
+ 1. Prerequisites: Ensure that the patient with the specified ID exists in the system.
+
+ 2. Test case: `addR z/1234 r/` (no text or only spaces after the remarks prefix)
+ Expected: No remarks are added. An error message is displayed, indicating that remarks cannot be empty.
+
+
+5. Adding remarks with a very long text
+
+ 1. Prerequisites: Ensure that the patient with the specified ID exists in the system.
+
+ 2. Test case: `addR z/1234 r/Patient's condition improved dramatically after treatment. Long-term prognosis looks positive.` (long remark)
+ Expected: The entire text of the remark is successfully added to the patient with ID 1234. A confirmation message is displayed with the full added remark.
+
+
+### Checking an appointment
+
+1. Check appointments with valid doctor ID and date
+
+ 1. Prerequisites: Ensure that the doctor with the specified ID exists in the system and has appointments scheduled on the specified date.
+
+ 2. Test case: `checkA z/01 y/2023-09-25`
+ Expected: The list of appointments for Doctor with ID 01 on 2023-09-25 is displayed. If appointments are present, details of each appointment are shown.
+
+
+2. Check appointments for a doctor with no appointments on the specified date
+
+ 1. Prerequisites: Ensure that the doctor with the specified ID exists in the system but has no appointments on the specified date.
+
+ 2. Test case: `checkA z/01 y/2023-11-15`
+ Expected: No appointments are found for Doctor with ID 01 on 2023-11-15. A message "No appointment found for Doctor: [Doctor Name]" is displayed.
+
+
+3. Check appointments with a non-existent doctor ID
+
+ 1. Test case: `checkA z/999 y/2023-09-25` (where Doctor ID 999 does not exist in the system)
+ Expected: No appointments are found. An error message is displayed.
+
+
+4. Check appointments with a missing date parameter
+
+ 1. Prerequisites: Ensure that the doctor with the specified ID exists in the system.
+
+ 2. Test case: `checkA z/01` (no date specified)
+ Expected: An error message "No date time is given for Doctor appointment: [Doctor Name]" is displayed, indicating that the date parameter is missing.
+
+
+5. Check appointments with a doctor having multiple patients on the same day
+
+ 1. Prerequisites: Ensure that the doctor with the specified ID exists and has multiple appointments scheduled with different patients on the same date.
+
+ 2. Test case: `checkA z/01 y/2023-10-20`
+ Expected: A list of all appointments for Doctor with ID 01 on 2023-10-20 is displayed. Each appointment includes details of the patient, appointment time, and any remarks.
+
+
+6. Check appointments with an invalid date format
+
+ 1. Test case: `checkA z/01 y/25-09-2023` (incorrect date format)
+ Expected: An error message is displayed, indicating that the date format is invalid. The command should prompt the user to enter the date in the correct format (YYYY-MM-DD).
+
+7. Check appointments with future date (no appointments yet)
+
+ 1. Prerequisites: Ensure that the doctor has no appointments scheduled for a future date.
+
+ 2. Test case: `checkA z/01 y/2030-01-01`
+ Expected: No appointments are found. A message "No appointment found for Doctor: [Doctor Name]" is displayed.
+
+
+### Marking an appointment
+
+1. Mark an existing appointment as complete with valid doctor and patient IDs
+
+ 1. Prerequisites: Ensure that an appointment exists between the specified doctor and patient at the specified time.
+
+ 2. Test case: `mark z/1234 z/5679 x/2024-12-31 15:23`
+ Expected: The appointment between Patient with ID 1234 and Doctor with ID 5679 on 2024-12-31 at 15:23 is marked as complete. A message "Successfully marked appointment as complete" is displayed.
+
+
+2. Mark a non-existent appointment as complete
+
+ 1. Prerequisites: Ensure that no appointment exists between the specified doctor and patient at the specified time.
+
+ 2. Test case: `mark z/1234 z/5679 x/2025-01-01 10:00`
+ Expected: An error message "The appointment doesn't exist!" is displayed, as there is no appointment to mark as complete.
+
+
+3. Mark an appointment with a non-existent ID
+
+ 1. Test case: `mark z/1234 z/9999 x/2024-12-31 15:23` (where Doctor ID 9999 does not exist)
+ Expected: An error message is displayed, indicating that the doctor ID is invalid.
+
+ 2. Test case: `mark z/9999 z/5679 x/2024-12-31 15:23` (where Patient ID 9999 does not exist)
+ Expected: An error message is displayed, indicating that the patient ID is invalid.
+
+
+4. Mark an appointment with a missing appointment time parameter
+
+ 1. Prerequisites: Ensure that the doctor and patient IDs are valid and that there is an existing appointment.
+
+ 2. Test case: `mark z/1234 z/5679` (no date specified)
+ Expected: An error message indicating that the date/time parameter is missing and required for marking an appointment as complete.
+
+
+5. 1. Mark an appointment with an invalid date format
+ 1. Test case: `mark z/1234 z/5679 x/31-12-2024 15:23` (incorrect date format)
+ Expected: An error message indicating that the date format is invalid. The command should prompt the user to enter the date in the correct format (YYYY-MM-DD HH
+ ).
+
+
+6. Mark an appointment for a doctor and patient with an appointment in the past
+
+ 1. Prerequisites: Ensure that an appointment exists in the past between the doctor and patient.
+
+ 2. Test case: `mark z/1234 z/5679 x/2023-01-01 10:00`
+ Expected: The appointment is marked as complete if it exists. If marked, a success message is shown. If the appointment does not exist, an error message is displayed.
+
+### Getting ID of a person
+
+1. Get ID with an exact match of the name
+ 1. Prerequisites: Ensure a person with the name "John Philips" exists in the address book.
+
+ 2. Test case: `get John Philips`
+ Expected: The ID of "John Philips" is returned. A message like "ID: [ID]" is displayed.
+
+
+2. Get ID with a partial match of the name
+
+ 1. Prerequisites: Ensure a person with the name "John Philips" exists in the address book.
+
+ 2. Test case: `get John`
+ Expected: The ID of "John Philips" is returned if there is only one match. If there are multiple matches, the ID of the first match is returned.
+
+
+3. Get ID when the name does not exist
+
+ 1. Test case: `get Nhoj Eod`
+ Expected: An error message is displayed, as there is no match for "Nhoj Eod".
+
+
+4. Get ID when there is no input provided
+
+ 1. Test case: `get`
+ Expected: An error message prompting for input. Command should not execute without keywords.
+
+
+5. Get ID with numeric characters in the name
+
+ 1. Prerequisites: Ensure a person with the name "John123" exists in the address book.
+
+ 2. Test case: `get John123`
+ Expected: The ID of "John123" is returned.
+
+### Viewing a person's history
+
+1. View full history of a patient by ID
+
+ 1. Prerequisites: Ensure the patient with ID 2 has a recorded medical history.
+
+ 2. Test case: `view z/2`
+ Expected: All recorded history for patient ID 2 is displayed.
+
+
+2. View history on a specific date and time
+
+ 1. Prerequisites: Ensure the patient with ID 2 has a recorded appointment on 2023-09-25 10:15.
+
+ 2. Test case: `view z/2 x/2023-09-25 10:15`
+ Expected: Only the history of the specific appointment on 2023-09-25 10:15 for patient ID 2 is displayed.
+
+
+3. View history for a date and time with no records
+
+ 1. Prerequisites: Ensure the patient with ID 2 does not have an appointment on 2024-01-01 12:00.
+
+ 2. Test case: `view z/2 x/2024-01-01 12:00 `
+ Expected: An error message is displayed, as there is no history for that date and time.
+
+
+4. View history for a non-existent patient ID
+
+ 1. Test case: `view z/9999`
+ Expected: An error is displayed, as there is no patient with ID 9999.
+
+
+5. View history with invalid date format
+ 1. Test case: `view z/2 x/2023/09/25 10:15` (incorrect date format)
+ Expected: An error message is shown indicating invalid date format. Command should not execute due to improper input.
+
+
+6. View history when there are multiple history entries on the same date but different times
+
+ 1. Prerequisites: Ensure patient ID 2 has multiple history entries on 2023-09-25 at different times (e.g., 10:15 and 14:30).
+
+ 2. Test case: `view z/2 x/2023-09-25 10:15`
+ Expected: Only the history of the specific appointment at 10:15 on 2023-09-25 is displayed.
+
+ 3. Test case: `view z/2 x/2023-09-25`
+ Expected: If the command is adjusted to accept dates without time, it should display all history entries for 2023-09-25.
+
+
+7. View history for a patient with no history at all
+
+ 1. Prerequisites: Ensure the patient with ID 2 has no recorded history.
+
+ 2. Test case: `view z/2`
+ Expected: An error message is displayed, indicating no history entries for patient ID 2.
+
+
+8. View history by specifying both patient ID and invalid date-time combination
+
+ 1. Prerequisites: Ensure the patient with ID 2 does not have an appointment at the provided date-time.
+ 2. Test case: `view z/2 x/2024-12-31 15:23`
+ Expected: An error message is displayed, as no appointment or history exists for this date-time combination.
### Saving data
1. Dealing with missing/corrupted data files
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+ 1. Prerequisites: Have a valid `addressbook.json` data file in the expected location.
+ 2. Test case: Delete or rename the `addressbook.json` file and then launch the application.
+ Expected: The application should detect the missing data file and create a new, empty `addressbook.json` file upon startup. The user should see a message indicating that the data file was missing and a new one has been created.
+ 3. Test case: Corrupt the `addressbook.json` file by introducing invalid JSON syntax (e.g., remove a closing bracket or add an extra comma). Then, launch the application.
+ Expected: The application should detect the corrupted data file and display an error message.
+ 4. Test case: Replace `addressbook.json` with a non-JSON file (e.g., rename a text file to `addressbook.json`) and then launch the application.
+ Expected: The application should detect the invalid format and notify the user of the issue. The application should not crash and may prompt the user to reset or repair the data file.
+
+
+2. Restoring from backup when data file is missing
+
+ 1. Prerequisites: Delete the `addressbook.json` file. Ensure a backup file is present in the backup folder.
+ 2. Test case: Launch the application.
+ Expected: The application should detect the missing data file and offer to restore from the most recent backup. If the user agrees, the backup file is copied to `addressbook.json`, and the application starts with the restored data.
+
+--------------------------------------------------------------------------------------------------------------------
+## **Appendix: Effort**
+
+### Difficulty Level and Challenges
+
+The project’s complexity far surpassed typical single-entity systems like AB3, as it dealt with multiple interrelated entities such as doctors, patients, and appointments. Each entity had distinct attributes, behaviors, and interactions, making data management and system design more complicated. One of the major challenges was ensuring consistency in handling various entity types, while maintaining an intuitive and responsive user experience. The increased complexity required more sophisticated logic for tasks like filtering, and linking entities, making debugging and testing far more intensive than in simpler systems.
+
+We also faced challenges when we want to test the different entities and commands when doing unit and integration testing as it gets more complicated to build stubs that contain entities in a correct format.
+
+### Effort Required
+
+Substantial effort was required to design and implement the core system architecture, which needed to handle the complex relationships between entities without becoming overly rigid or error-prone. A considerable amount of time was invested in designing an extensible data model that could accommodate future requirements and scalability.
+
+The development process involved careful coordination between different aspects of the project, including data storage, UI, and logic. Ensuring that these components interacted seamlessly required numerous iterations and thorough testing, further increasing the overall effort.
+
+### Achievements
+
+Despite the challenges, the project achieved several important milestones. We successfully built a robust system capable of managing and processing doctors' appointements efficiently. The user interface was designed to be simple and efficient while allowing for advanced operations like filtering through complex data sets.
+
+Additionally, we integrated external libraries like JUnit for our testing and JavaFx for our UI components.
+
+Overall, the project successfully provides a specialised one-stop-for-all platform for doctors to their patients, schedules, appointments and to prioritise speed when accessing and updating patients’ information and details on a regular basis.
+
+
+
+
-1. _{ more test cases … }_
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index b0e740c27e9..1c5de495159 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -3,41 +3,176 @@ layout: page
title: User Guide
---
-MedDict is a **desktop application designed for physiotherapists** who manage a large number of patients. It simplifies data entry and retrieval, allowing quick access to contact details, patient conditions, and the progress of recurring or long-term patients. The application supports a streamlined process for tracking medical history, patient appointments, and treatment progress.
+
+Welcome to the **MedDict User Guide!** 🎉
+We're excited to have you on board with us 🥳🥳🥳
+
+**MedDict** is a desktop application designed for medical staff who manage a large number of patients. It simplifies data entry and retrieval, allowing quick access to contact details, patient conditions, and the progress of recurring or long-term patients. The application is designed with large databases in mind, supporting a streamlined process for tracking medical history, patient appointments, and treatment progress.
+
+Unlike most other applications who predominantly function on a **Graphical User Interface (GUI)** where most of the user's inputs and outputs are achieved via the use of a mouse or touchscreen, MedDict is built upon the philosophy that a **Command Line Interface (CLI)** -- where all features and utility can be achieved via typed-in commands -- could be far more efficient.
+
+
+
+With **MedDict**, we believe we can revolutionise your work and management experience! 💪
+
+With all that said, let's start you on your journey towards a new peak level of efficiency! 💯
+
+If you would like to skip to any specific part of the User Guide, you can refer to the table below! 😊
+
+
+
+
* Table of Contents
{:toc}
---------------------------------------------------------------------------------------------------------------------
+
-## Quick start
+## Quick Start
-1. Ensure you have Java `17` or above installed in your Computer.
+This section is for users who are experienced in installing and using Java executables. If you require a more detailed Quick Start guide, please click [here](#quick-start-beginner-friendly-detailed) or scroll past this section.
-1. Download the latest `.jar` file from [here](https://github.com/se-edu/addressbook-level3/releases).
+1. Ensure you have Java `17` or above installed in your device.
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+2. Download the latest `.jar` file from here.
-1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar addressbook.jar` command to run the application.
- A GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- 
+3. Copy or move the `.jar` file to the folder you want to use as the home folder for your MedDict application. We recommend creating a separate folder for the application as MedDict will create files in the directory it is saved in for storage purposes.
-1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+4. Open a command terminal, `cd` into the folder you put the `.jar` file in, and use the `java -jar addressbook.jar` command to run the application.
+ After completing the above, the application should open with a Graphical User Interface (GUI) similar to the one below should appear in a few seconds. Note that the interface may vary slightly depending on the Operating System (OS) and the presence of data.
+
+ 
+
+5. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try:
* `list` : Lists all contacts.
- * `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book.
+ * `createP n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 ` : Adds a contact named `John Doe` to the Address Book with the specified information.
- * `delete 3` : Deletes the 3rd contact shown in the current list.
+ * `delete z/2` : Deletes the person with the specified ID of 2. (Won't work if you don't have a patient with an ID of 2!)
* `clear` : Deletes all contacts.
* `exit` : Exits the app.
-1. Refer to the [Features](#features) below for details of each command.
+6. That's all for the setup! If you require a more detailed set-up guide, you can scroll down to our [detailed quick start guide](#quick-start-beginner-friendly-detailed). Otherwise, you can refer to the [Features Section below](#features) for details of each command, alternatively, check out the [summary of commands here!](#command-summary)
+
+
+
+## Quick Start (beginner-friendly, detailed)
+
+If you are less experienced in installing and using Java executables, no worries! The set-up is relatively simple 😉, and we will be guiding you with each step.
+
+If anytime throughout the set-up, you feel lost or feel like you may require more assistance, try searching through our [FAQ Section](#faq). If you still require more assistance, feel free to reach out on our GitHub Discussions Page!
+
+⬇️ With all that said, let's get started! ⬇️
+
+1. **Make sure Java 17 or higher is installed on your computer.**
+
+ * To Check if Java is Installed:
+
+ 1. Open your terminal:
+ - **Windows**: Press `Windows + R`, type `cmd`, and press Enter.
+ - **Mac**: Press `Command + Space`, type `Terminal`, and press Enter.
+ - **Linux**: Press `Ctrl + Alt + T`, or look for "Terminal" in your applications menu.
+
+ 2. In the terminal, enter the following command and press Enter:
+
+ ```bash
+ java -version
+ ```
+
+ 3. If Java 17 or higher is installed, you should see a version similar to this:
+
+ ```bash
+ java version "17.0.x" 2024-xx-xx LTS
+ ```
+ If you see this, you can skip the step below.
+
+ 4. (Only if you do not have Java 17) If you do not have Java 17 installed, continue with the following steps to install Java 17.
+ 1. Visit [Oracle’s Java 17 download page](https://www.oracle.com/java/technologies/javase-jdk17-downloads.html).
+ 2. Download and install the correct Java Development Kit (JDK) for your operating system by following the on-screen instructions.
+ 3. Once installed, run the `java -version` command again to confirm that Java is installed correctly.
+
+2. After verifying that you have the correct version of Java installed, **download the latest `.jar` file as follows:**
+ 1. Go to our GitHub release page.
+ 2. Find the latest version of MedDict on our release page. Typically, it should be the release at the top of the page, and should have the largest number (e.g. v1.0.2 is a more updated version than v0.2.2).
+ 3. Download (by clicking) the `.jar` file from the website by scrolling to the "Assets" portion of the latest release notes (bottom section of the release notes). An example of a `.jar` file is `meddict-v0.1.1-alpha.jar` under the v0.1.1-alpha release notes.
+
+3. **Copy the `.jar` file to the folder you want to use as the home folder for MedDict.**
+ We recommend creating a separate folder for the application as MedDict will create files in the directory it is saved in for storage purposes.
+ Depending on your Operating System (OS):
+
+ * **Windows:**
+ 1. Open File Explorer and navigate to where the `.jar` file is saved in, typically, this is the Downloads folder.
+ 2. Right-click on the `.jar` file and select Copy.
+ 3. Go to the destination folder where you want to store the application, right-click, and select Paste.
+
+ * **Mac:**
+ 1. Open Finder and navigate to where the `.jar` file is saved in, typically, this is the Downloads folder.
+ 2. Right-click (or use `Control + Click`) on the `.jar` file and choose Copy.
+ 3. Go to the destination folder where you want to store the application, right-click, and select Paste.
+
+ * **Linux:**
+ 1. Open File Manager and navigate to where the `.jar` file is saved in, typically, this is the Downloads directory.
+ 2. Right-click on the `.jar` file and choose Copy.
+ 3. Go to the destination folder where you want to store the application, right-click, and select Paste.
+
+4. **Open a command terminal, navigate to the folder where the `.jar` file is saved using the `cd` command, and then run the application with the following command.**
+ Depending on your Operating System (OS):
+ * **Windows:**
+ 1. Open the folder where the `.jar` file is saved. (If you have just finished step 3 above, the folder should still be open)
+ 2. To get the full path of this folder:
+ - Right-click on the folder and select Properties.
+ - In the General tab, locate the Location field and copy the path. (Alternatively, open the folder, click on the address bar, and copy the full path, e.g., `C:\Users\YourName\Documents\MedDict`).
+ 3. Open the Command Prompt:
+ - Press `Windows + R`, type `cmd`, and press Enter.
+ - Use the `cd` command and paste (`Ctrl + V`) the copied path to navigate to the folder where the `.jar` file is saved. For example:
+ ```
+ cd C:\Users\YourName\Documents\MedDict
+ ```
+ 4. Run the application according to the name of the jar file downloaded:
+ For example, if the name of the jar file is `meddict-v1.6.jar`, type the following:
+ ```bash
+ java -jar meddict-v1.6.jar
+ ```
+ * **Mac/Linux:**
+ 1. Open the Terminal by searching for it or by pressing `Ctrl + Alt + T`.
+ 2. To get the full path of the folder where the `.jar` file is located:
+ - Open Finder (Mac) or File Explorer (Linux).
+ - Navigate to the folder where you saved the `.jar` file. (If you have just finished step 3 above, the folder should still be open)
+ - Right-click on the folder and choose Get Info (Mac) or Properties (Linux) to see the full path, or press `Cmd + Option + C` (Mac) to copy it.
+ 3. Use the `cd` command and paste the copied path to go to the folder where the `.jar` file is saved. For example:
+ ```
+ cd /Users/YourName/Documents/MedDict
+ ```
+ 4. Run the application according to the name of the jar file downloaded:
+ For example, if the name of the jar file is `meddict-v1.6.jar`, type the following:
+ ```bash
+ java -jar meddict-v1.6.jar
+ ```
+ ---
+ After completing the above, the application should open with a Graphical User Interface (GUI) similar to the one below should appear in a few seconds. Note that the interface may vary slightly depending on the Operating System (OS) and the presence of data.
+
+ 
+5. If you've reached this step, **🎉 CONGRATULATIONS!!! 🎉 MedDict has been installed successfully on your device!**
+ What's next is to try out some of MedDict's commands. Type the command in the command box by clicking on the empty bar at the top, typing a command and pressing Enter on your keyboard to execute it. (e.g. typing `help` and pressing Enter will open the help window.)
+ Some example commands you can try:
+
+ * `list` : Lists all contacts.
---------------------------------------------------------------------------------------------------------------------
+ * `createP n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 ` : Adds a contact named `John Doe` to the Address Book with the specified information.
+
+ * `delete z/2` : Deletes the person with the specified ID of 2. (Won't work if you don't have a person with an ID of 2!)
+
+ * `clear` : Deletes all contacts.
+
+ * `exit` : Exits the app.
+
+6. That's all for the setup! Refer to the [Features Section below](#features) for details of each command, alternatively, check out the [summary of commands here!](#command-summary)
+
+
## Features
@@ -46,13 +181,10 @@ MedDict is a **desktop application designed for physiotherapists** who manage a
**:information_source: Notes about the command format:**
* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+ e.g. in `delete z/ID`, `ID` is a parameter which can be used as `delete z/01`.
* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
-
-* Items with `…` after them can be used multiple times including zero times.
- e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+ e.g. `n/NAME [r/REMARK]` can be used as `n/John Doe r/friend` or as `n/John Doe`.
* Parameters can be in any order.
e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
@@ -60,140 +192,438 @@ MedDict is a **desktop application designed for physiotherapists** who manage a
* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+* The output messages you may see in your own application when running the commands may differ slightly from the example output. This could be due to the different databases present in your own local application and of that present in the example outputs, or due to the example outputs being demonstrated on a different device than yours. Regardless, where relevant, you can refer to the error messages provided in the event that a command did not work as intended.
+
+* Some variations in terminology in the example outputs such as `id` and `ID` are interchangeable unless stated otherwise. In this case, `id` or `ID` or `Id` all refer to one's identification number (within the database).
+
* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application.
+
+* If you are using a PDF version of this document, highlighting and copying commands or lines may lead to unintended special characters, symbols or whitespaces being added to the clipboard (the text that was copied). Hence, to avoid pasting unintended commands into the application, do double-check the commands when you are copy-pasting.
+
+For your convenience and easy reference, you can click on the header of the command to go to the command summary table!
+
+Likewise, you can click on a command from the command summary table to read about its specific implementation.
+
+For example, try clicking on "Viewing Help" in the "Viewing Help: `help`" section below!
+
-Shows a message explaning how to access the help page.
+### [Viewing Help](#command-summary): `help`
-
+Displays a message with a link to the User Guide (you're here right now!).
Format: `help`
+Examples:
+* `help`
+
+
+### [Creating and Adding a Doctor](#command-summary): `createD`
+
+Creates a doctor with given details and adds the doctor to the MedDict database.
+
+Format: `createD n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS`
+
+* **NAME**: Only alphanumeric characters and spaces; cannot be blank.
+* **PHONE_NUMBER:** Numeric only; minimum of 3 digits.
+* **EMAIL**: Must follow standard email format 'local-part@domain.com', where the local part contains only alphanumeric characters and certain special characters,
+ but cannot start or end with these special characters (+_.-). The domain consists of labels separated by periods,
+ ending with a label at least two characters long, with each label starting and ending with an alphanumeric character and allowing hyphens in between.
+* **ADDRESS**: Address of the doctor.
+* **Note:**: Duplicate doctors (same name, phone, and email) are not allowed.
+* A _notification message_ will be displayed if MedDict could not create the doctor with the given information.
+
+Examples:
+* `createD n/Dr Jane Smith p/87654321 e/dr.jane.smith@hospital.com a/456 Elm Street`
+ Dr Jane Smith; Phone: 87654321; Email: dr.jane.smith@hospital.com; Address: 456 Elm Street;
+
+* `createD n/Dr Jane Smith p/87654321 e/dr.jane.smith@hospital.com a/456 Elm Street`
+ This doctor already exists.
+
-### Adding a person: `add`
+### [Creating and Adding a Patient](#command-summary): `createP`
-Adds a person to the address book.
+Creates a patient with given details and adds the patient to the MedDict database.
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+Format: `createP n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS`
+
+* **NAME**: Only alphanumeric characters and spaces; cannot be blank.
+* **PHONE_NUMBER:** Numeric only; minimum of 3 digits.
+* **EMAIL**: Must follow standard email format 'local-part@domain.com', where the local part contains only alphanumeric characters and certain special characters,
+ but cannot start or end with these special characters (+_.-). The domain consists of labels separated by periods,
+ ending with a label at least two characters long, with each label starting and ending with an alphanumeric character and allowing hyphens in between.
+* **ADDRESS**: Address of the patient.
+* **Note**: Duplicate patients (same name, phone, or email) are not allowed.
+* A _notification message_ will be displayed if MedDict could not create the patient with the given information.
+
+
+Examples:
+* `createP n/John Doe p/98765432 e/johndoe@example.com a/123 Baker Street`
+ John Doe; Phone: 98765432; Email: johndoe@example.com; Address: 123 Baker Street;
+
+* `createP n/John Doe p/98765432 e/johndoe@example.com a/123 Baker Street`
+
+
Tip! You may notice that patient contacts created have an even-numbered ID while doctor contacts have an odd-numbered ID. Where relevant, you can use this information to your advantage! For example, instead of checking the UI to see whether the person contact is a patient or a doctor, you can determine their role based on their ID!
-
:bulb: **Tip:**
-A person can have any number of tags (including 0)
+### [Deleting a Person](#command-summary): `delete`
+
+Deletes the person with the specified `ID` from the MedDict database.
+
+Format: `delete z/ID`
+
+* **ID**: Must be valid, present in the MedDict database.
+* A _notification message_ will be displayed if MedDict could not delete the person with the given ID.
+
+Examples:
+* `delete z/2`
+ **Output**:
+ Successfully deleted the person.
+
+* `delete z/2`
+ **Output**:
+ Unable to delete the person, check the ID entered!
+
+### [Add a Remark to a Patient](#command-summary): `addR`
+
+Adds a remark to an existing patient with the specified `PATIENT_ID` in the MedDict database in address book.
+
+Format: `addR z/PATIENT_ID r/REMARK`
+
+* **PATIENT_ID**: Must be valid, present in the MedDict database, and an _even integer_ (0, 2, 4, …).
+* A _notification message_ will be displayed if MedDict could not add remarks to the patient with the given ID.
+
Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+* `addR z/0 r/cancer`
+ **Output**:
+ Successfully added remarks: cancer to patient of ID: 0.
+
+
-### Listing all persons : `list`
+### [Listing All Persons](#command-summary): `list`
-Shows a list of all persons in the address book.
+Displays a list of all persons in the address book.
Format: `list`
-### Editing a person : `edit`
+Examples:
+* `list`
+ **Output**:
+ 
+
+
-Edits an existing person in the address book.
+### [Editing a Person](#command-summary): `edit`
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+Edits an existing person with the specified `ID` in the database.
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …
+Format: `edit z/ID [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS]`
+
+* **ID**: The Person ID must be valid, present in the MedDict database, and an _integer_ (0, 1, 2, …).
* At least one of the optional fields must be provided.
* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person’s tags by typing `t/` without
- specifying any tags after it.
+* Editing the person with the same details as the existing detail is not allowed.
+* A _notification message_ will be displayed if MedDict could not edit the person with the given ID.
+
+Examples:
+* `edit z/1 p/91234567 e/johndoe@example.com`
+ **Output**:
+ Edited Person: Dr Jane Smith; Phone: 91234567; Email: johndoe@example.com; Address: 456 Elm Street;
+
+* `edit z/2`
+ **Output**:
+ At least one field to edit must be provided.
+
+* `edit z/1 p/91234567 e/johndoe@example.com`
+ **Output**:
+ This person already exists in the address book.
+
+### [Getting ID of Doctor or Patient by Name](#command-summary): `get`
+
+Gets the ID of a doctor or patient whose names contain any of the given keywords.
+
+Format: `get KEYWORD`
+
+* The search is case-insensitive. e.g. `hans` will match `Hans`
+* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+* Only the name is searched.
+* Only full words will be matched e.g. `Han` will not match `Hans`
+* Persons matching at least one keyword will be returned (i.e. `OR` search).
+ e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+* A _notification message_ will be displayed if MedDict could not find a person associated with the KEYWORD.
Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+* `get john`
+ **Output**:
+ The ID of the person that you are finding is: 0
+
+* `get johnny`
+ **Output**:
+ Invalid name entered! Check the name that you want to search ID for! Key in 'list' to view all patients
-### Locating persons by name: `find`
+* `get johnny`
+ **Output**:
+ 2 persons listed that suits your keyword!
+ Enter more specific name keywords to retrieve the ID of the person
-Finds persons whose names contain any of the given keywords.
+### [Finding Doctor or Patient by Name](#command-summary): `find`
-Format: `find KEYWORD [MORE_KEYWORDS]`
+Finds a doctor or patient whose names contain any of the given keywords.
-* The search is case-insensitive. e.g `hans` will match `Hans`
+Format: `find KEYWORD`
+
+* The search is case-insensitive. e.g. `hans` will match `Hans`
* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
* Only the name is searched.
* Only full words will be matched e.g. `Han` will not match `Hans`
* Persons matching at least one keyword will be returned (i.e. `OR` search).
e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+* A _notification message_ will be displayed if MedDict could not find a person associated with the KEYWORD.
Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- 
+* `find john`
+ **Output**:
+ One person listed! Key in 'list' to view all patients
+
+* `find `
+ **Output**:
+ Invalid name entered! Check the name that you want to search ID for!
+ Key in 'list' to view all patients
-### Deleting a person : `delete`
+* `find johnny`
+ **Output**:
+ 2 persons listed that suits your keyword!
+ Enter more specific name keywords to retrieve the ID of the person
-Deletes the specified person from the address book.
+### [Adding an Appointment](#command-summary): `addA`
-Format: `delete INDEX`
+Adds an appointment to an existing patient with the specified `PATIENT_ID` and doctor with the specified `DOCTOR_ID` in the MedDict database.
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
-* The index **must be a positive integer** 1, 2, 3, …
+Format: `addA z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME [r/REMARK]`
+
+
+ Warning! Usually, the order of parameters in the command do not matter. However, in this case, do take extra effort to ensure you key in z/PATIENT_ID before z/DOCTOR_ID. Remember, the patient always comes first! 😉
+
+
+* **Patient ID**: Must be valid, present in the MedDict database, and an _even integer_ (0, 2, 4, …).
+* **Doctor ID**: Must be valid, present in the MedDict database, and an _odd integer_ (1, 3, 5, …).
+* **DateTime**: Must use _yyyy-MM-dd HH:mm_ format (e.g. 2024-12-31 23:59).
+* **Remark**: Optional, user can add remark details by adding `[r/Remark]` when calling the command.
+ Empty remark will be added to the appointment if remark is not specified.
+* When adding appointment, the appointment detail will be added to both the patient's and doctor's appointment lists.
+* Each appointment must be scheduled at a unique time to prevent overlap for both the patient and the doctor.
+* A _notification message_ will be displayed if MedDict could not add the appointment successfully.
Examples:
-* `list` followed by `delete 2` deletes the 2nd person in the address book.
-* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command.
+* `addA z/0 z/1 x/2024-12-31 15:23 r/Third physiotherapy session`
+ **Output**:
+ Successfully added appointment to a patient.
+
+* `addA z/0 z/1 x/2024-12-31 15:23`
+ **Output**:
+ Successfully added appointment to a patient.
+
+* `addA z/0 z/1 x/2024-12-31 15:23`
+ **Output**:
+ The patient or doctor already has another appointment!
+
+
-### Clearing all entries : `clear`
+### [View History of a Person](#command-summary): `view`
-Clears all entries from the address book.
+Displays the history of an existing person with the specified `ID` in the MedDict database.
+
+Format: `view z/ID [x/DATE_TIME]`
+
+* **ID**: Must be valid, present in the MedDict database.
+* **DateTime**: Optional, user can view history of the patient on a specific date by adding `[x/DATE_TIME]` when calling the command. Must use _yyyy-MM-dd HH:mm_ format (e.g. 2024-12-31 23:59).
+* A _notification message_ will be displayed if MedDict could not find any history or appointments associated with the person's ID.
+
+Examples:
+* `view z/0 x/2024-12-31 15:23`
+ **Output**:
+ \[Incomplete] Appointment: `2024-12-31 15:23` for `0` (patient id) with `1` (doctor id). Remarks: `Third physiotherapy session`.
+
+* `view z/0`
+ **Output**:
+ \[Completed] Appointment: `2024-12-31 15:23` for `0` (patient id) with `1` (doctor id). Remarks: `Third physiotherapy session`.
+ \[Incomplete]Appointment: `2024-12-31 16:23` for `0` (patient id) with `1` (doctor id). Remarks: `Fourth physiotherapy session`.
+
+* `view z/1 x/2024-12-31 16:23`
+ **Output**:
+ No history found for the person.
+
+### [Check Appointments of a Person](#command-summary): `checkA`
+
+Checks the appointments of an existing person with the specified `ID` in the MedDict database.
+
+Format: `checkA z/ID y/DATE`
+
+* **ID**: Must be valid, present in the MedDict database.
+* A _notification message_ will be displayed if MedDict could not find any appointments associated with the person's ID.
+
+Examples:
+* `checkA z/1 y/2024-12-31`
+ **Output**:
+ Appointments on 2024-12-31:
+ \[Incomplete] Appointment: `2024-12-31` for `0` (patient id) with `1` (doctor id). Remarks: `Third physiotherapy session`
+ \[Completed] Appointment: `2024-12-31` for `0` (patient id) with `1` (doctor id). Remarks: `Fourth physiotherapy session`
+
+* `checkA z/2 y/2024-12-30`
+ **Output**:
+ No appointment found for the person: `Amy Bee`
+
+### [Mark Appointment of a Doctor](#command-summary): `mark`
+
+Marks appointment associated with the specified `PATIENT_ID`, `DOCTOR_ID`, `DATE_TIME` in the MedDict database.
+
+Format: `mark z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME`
+
+
+ Warning! Usually, the order of parameters in the command do not matter. However, in this case, do take extra effort to ensure you key in z/PATIENT_ID before z/DOCTOR_ID. Remember, the patient always comes first! 😉
+
+
+* **Patient ID**: Must be valid, present in the MedDict database, and an _even integer_ (0, 2, 4, …).
+* **Doctor ID**: Must be valid, present in the MedDict database, and an _odd integer_ (1, 3, 5, …).
+* **DateTime**: Must use _yyyy-MM-dd HH:mm_ format (e.g. 2024-12-31 23:59).
+* A _notification message_ will be displayed if MedDict could not find the appointment to mark.
+
+Examples:
+* `mark z/0 z/1 x/2024-12-31 15:23`
+ **Output**:
+ Successfully marked appointment as complete
+
+* `mark z/0 z/1 x/2024-12-31 15:23`
+ **Output**:
+ The appointment is completed. Check the appointment that you want to mark!
+
+* `mark z/2 z/3 x/2024-12-31 16:23`
+ **Output**:
+ No appointments found on this date.
+
+
+
+### [Delete Appointment](#command-summary): `deleteA`
+
+Deletes appointment associated with the specified `PATIENT_ID`, `DOCTOR_ID`, `DATE_TIME` from the MedDict database.
+
+Format: `deleteA z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME`
+
+
+ Warning! Usually, the order of parameters in the command do not matter. However, in this case, do take extra effort to ensure you key in z/PATIENT_ID before z/DOCTOR_ID. Remember, the patient always comes first! 😉
+
+
+* **Patient ID**: Must be valid, present in the MedDict database, and an _even integer_ (0, 2, 4, …).
+* **Doctor ID**: Must be valid, present in the MedDict database, and an _odd integer_ (1, 3, 5, …).
+* **DateTime**: Must use _yyyy-MM-dd HH:mm_ format (e.g. 2024-12-31 23:59).
+* A _notification message_ will be displayed if MedDict could not find the appointment to delete.
+
+Examples:
+* `deleteA z/0 z/1 x/2024-12-31 15:23`
+ **Output**:
+ Successfully deleted appointment to a patient
+
+* `deleteA z/1 z/3 x/2024-12-31 15:23`
+ **Output**:
+ The appointment doesn't exist! Please check again the details you have entered!
+
+
+
+### [Clearing All Entries](#command-summary): `clear`
+
+Clears all entries from the database, in other words, delete all contacts from the database.
Format: `clear`
-### Exiting the program : `exit`
+Examples:
+* `clear`
+ **Output**:
+ 
+
+### [Exiting the Program](#command-summary): `exit`
Exits the program.
Format: `exit`
-### Saving the data
+
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+### Saving the Data
-### Editing the data file
+The data is saved in the hard disk automatically after any command changes the data. There is no need to save manually.
-AddressBook data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
+### Editing the Data File
+
+The data is saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
:exclamation: **Caution:**
-If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
-Furthermore, certain edits can cause the AddressBook to behave in unexpected ways (e.g., if a value entered is outside of the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
+If your changes to the data file makes its format invalid, MedDict will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
+Furthermore, certain edits can cause MedDict to behave in unexpected ways (e.g., if a value entered is outside the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
-### Archiving data files `[coming in v2.0]`
+--------------------------------------------------------------------------------------------------------------------
-_Details coming soon ..._
+## Known issues
---------------------------------------------------------------------------------------------------------------------
+1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again.
+2. **If you minimize the Help Window** and then run the `help` command (or use the `Help` menu, or the keyboard shortcut `F1`) again, the original Help Window will remain minimized, and no new Help Window will appear. The remedy is to manually restore the minimized Help Window.
+3. **When using sample dataset**, if you were to use `addR` on the sample dataset, on some devices, there were occasional occurrences of a bug where it would add the remarks to all people in the sample database. Thus, to avoid this, we recommend you to use the `clear` command and try out the different commands on a fresh dataset of your own creation.
+
+
## FAQ
-**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+**Q1**: I am left-clicking to open the file but nothing happens / there is an error message!
+**A1**: To open and run MedDict, please refer to the [Quick Start Guide](#quick-start)!
---------------------------------------------------------------------------------------------------------------------
+**Q2**: How do I transfer my data to another Computer?
+**A2**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder. If you are unsure what this means, you can refer to the answer to Q3 below.
-## Known issues
+**Q3**: I want to update my version of MedDict with the newest version, how do I transfer my data? Is that possible?
+**A3**: No worries, you can easily transfer your data! Refer to the steps below.
-1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again.
-2. **If you minimize the Help Window** and then run the `help` command (or use the `Help` menu, or the keyboard shortcut `F1`) again, the original Help Window will remain minimized, and no new Help Window will appear. The remedy is to manually restore the minimized Help Window.
+1. Navigate to the folder where you saved the `.jar` file. (Similar to steps in the [Detailed Quick Start Guide](#quick-start-beginner-friendly-detailed))
+2. In that folder, find a folder titled data (e.g. `C:\Users\YourName\Documents\MedDict\data`)
+3. Inside the folder, there should be a file titled addressbook.json, copy or backup this file into a safe location. (e.g. `C:\Users\YourName\Documents\MedDict\data\addressbook.json`)
+4. Download the new release or version of MedDict (you can refer to the [Quick Start Guide](#quick-start) if needed)
+5. Open / run the application once.
+6. Close the application.
+7. Go to where the new MedDict `.jar` file is located in, and repeat steps 2 to 3.
+8. Replace the new addressbook.json file in the current data folder with the previous addressbook.json file that you have copied or saved. You can do this by copying the addressbook.json file from the old data folder and pasting it in the new data folder. When prompted to overwrite, click yes. Alternatively, you can use a text editor of your choice to edit the new and old addressbook.json file, then copy and paste all the content from the old addressbook.json file to the new one.
---------------------------------------------------------------------------------------------------------------------
+
## Command summary
-Action | Format, Examples
---------|------------------
-**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
-**Clear** | `clear`
-**Delete** | `delete INDEX`
e.g., `delete 3`
-**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
e.g.,`edit 2 n/James Lee e/jameslee@example.com`
-**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake`
-**List** | `list`
-**Help** | `help`
+| Action | Format, Examples |
+|-----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
+| **[Help](#viewing-help-help)** | `help`
Shows help page |
+| **[Create Doctor](#creating-and-adding-a-doctor-created)** | `createD n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS`
e.g., `createD n/Dr Jane p/87654321 e/dr.jane.smith@hospital.com a/456 Elm Street` |
+| **[Create Patient](#creating-and-adding-a-patient-createp)** | `createP n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS`
e.g., `createP n/John Doe p/98765432 e/johndoe@example.com a/123 Baker Street` |
+| **[Delete Person](#deleting-a-person-delete)** | `delete z/ID`
e.g., `delete z/2` |
+| **[Add Notes](#add-a-remark-to-a-patient-addr)** | `addR z/PATIENT_ID r/REMARK`
e.g., `addR z/0 r/cancer` |
+| **[List](#listing-all-persons-list)** | `list`
Shows all persons in address book |
+| **[Edit](#editing-a-person-edit)** | `edit z/ID [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS]`
e.g., `edit z/2 p/91234567 e/johndoe@example.com` |
+| **[Get ID](#getting-id-of-doctor-or-patient-by-name-get)** | `get KEYWORD`
e.g., `get john` |
+| **[Add Appointment](#adding-an-appointment-adda)** | `addA z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME r/REMARK`
e.g., `addA z/0 z/1 x/2024-12-31 15:23 r/Third physiotherapy session` |
+| **[View History](#view-history-of-a-person-view)** | `view z/ID [x/DATE_TIME]`
e.g., `view z/0 x/2024-12-31 15:23` |
+| **[Check Appointment](#check-appointments-of-a-person-checka)** | `checkA z/ID y/DATE`
e.g., `checkA z/1 y/2024-12-31` |
+| **[Mark Appointment](#mark-appointment-of-a-doctor-mark)** | `mark z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME`
e.g., `mark z/0 z/1 x/2024-12-31 15:23` |
+| **[Delete Appointment](#delete-appointment-deletea)** | `deleteA z/PATIENT_ID z/DOCTOR_ID x/DATE_TIME`
e.g., `deleteA z/1 z/3 x/2024-12-31 15:23` |
+| **[Clear](#clearing-all-entries-clear)** | `clear`
Clears all entries |
+| **[Exit](#exiting-the-program-exit)** | `exit`
Exits the program |
+
+
diff --git a/docs/_sass/minima/initialize.scss b/docs/_sass/minima/initialize.scss
index 30288811151..98005ba2b31 100644
--- a/docs/_sass/minima/initialize.scss
+++ b/docs/_sass/minima/initialize.scss
@@ -1,9 +1,10 @@
@charset "utf-8";
+@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
// Define defaults for each variable.
-$base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Segoe UI Symbol", "Segoe UI Emoji", "Apple Color Emoji", Roboto, Helvetica, Arial, sans-serif !default;
-$code-font-family: "Menlo", "Inconsolata", "Consolas", "Roboto Mono", "Ubuntu Mono", "Liberation Mono", "Courier New", monospace;
+$base-font-family: 'Roboto', -apple-system, BlinkMacSystemFont, "Segoe UI", "Segoe UI Symbol", "Segoe UI Emoji", "Apple Color Emoji", Helvetica, Arial, sans-serif !default;
+$code-font-family: "Roboto Mono", "Menlo", "Inconsolata", "Consolas", "Ubuntu Mono", "Liberation Mono", "Courier New", monospace;
$base-font-size: 16px !default;
$base-font-weight: 400 !default;
$small-font-size: $base-font-size * 0.875 !default;
diff --git a/docs/assets/css/style.scss b/docs/assets/css/style.scss
index b5ec6976efa..470c08e60d7 100644
--- a/docs/assets/css/style.scss
+++ b/docs/assets/css/style.scss
@@ -6,7 +6,34 @@
"minima/skins/{{ site.minima.skin | default: 'classic' }}",
"minima/initialize";
+@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
+
.icon {
height: 21px;
width: 21px
}
+
+.logo-site-header {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.logo-site-logo img {
+ height: 50px; /* Adjust the logo size as needed */
+}
+
+.logo-site-title {
+ font-size: 2em;
+ margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: 'Roboto', sans-serif; /* Example font for headers */
+ color: #F06449;
+}
+
+p, li, a {
+ font-family: 'Roboto', sans-serif; /* Example font for body text */
+}
+
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index 48b6cc4333c..4f68e2a3fd9 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -8,13 +8,13 @@ Participant ":Logic" as logic LOGIC_COLOR
Participant ":Model" as model MODEL_COLOR
Participant ":Storage" as storage STORAGE_COLOR
-user -[USER_COLOR]> ui : "delete 1"
+user -[USER_COLOR]> ui : "delete z/1"
activate ui UI_COLOR
-ui -[UI_COLOR]> logic : execute("delete 1")
+ui -[UI_COLOR]> logic : execute("delete z/1")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : delete(p)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
index 598474a5c82..486d914ec44 100644
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ b/docs/diagrams/BetterModelClassDiagram.puml
@@ -5,17 +5,13 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
AddressBook *-right-> "1" UniquePersonList
-AddressBook *-right-> "1" UniqueTagList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -right-> "*" Tag
UniquePersonList -right-> Person
-Person -up-> "*" Tag
-
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
+Person *--> "1" Name
+Person *--> "1" Phone
+Person *--> "1" Email
+Person *--> "1" Address
+Person *--> "*" Appointment
+Person *--> "1" ID
@enduml
diff --git a/docs/diagrams/ClearCommand-Logic.puml b/docs/diagrams/ClearCommand-Logic.puml
new file mode 100644
index 00000000000..e3bf2840449
--- /dev/null
+++ b/docs/diagrams/ClearCommand-Logic.puml
@@ -0,0 +1,49 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant "c:ClearCommand" as ClearCommand LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "a :AddressBook" as AddressBook MODEL_COLOR
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute(clear)
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand(clear)
+activate AddressBookParser
+
+create ClearCommand
+AddressBookParser -> ClearCommand
+activate ClearCommand
+
+ClearCommand --> AddressBookParser
+deactivate ClearCommand
+
+AddressBookParser --> LogicManager : c
+deactivate AddressBookParser
+
+LogicManager -> ClearCommand : execute()
+activate ClearCommand
+
+create AddressBook
+ClearCommand -> AddressBook
+activate AddressBook
+
+AddressBook -> Model : setAddressBook(a)
+deactivate AddressBook
+activate Model
+
+ClearCommand --> LogicManager : result
+deactivate ClearCommand
+deactivate Model
+
+[<-- LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/CreateDoctorCommand-Logic.puml b/docs/diagrams/CreateDoctorCommand-Logic.puml
new file mode 100644
index 00000000000..e6bff2beab8
--- /dev/null
+++ b/docs/diagrams/CreateDoctorCommand-Logic.puml
@@ -0,0 +1,71 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":CreateDoctorCommandParser" as CreateDoctorCommandParser LOGIC_COLOR
+participant "d:CreateDoctorCommand" as CreateDoctorCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("createDoctor XXX")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("createDoctor XXX")
+activate AddressBookParser
+
+create CreateDoctorCommandParser
+AddressBookParser -> CreateDoctorCommandParser
+activate CreateDoctorCommandParser
+
+CreateDoctorCommandParser --> AddressBookParser
+deactivate CreateDoctorCommandParser
+
+AddressBookParser -> CreateDoctorCommandParser : parse("XXX")
+activate CreateDoctorCommandParser
+
+create CreateDoctorCommand
+CreateDoctorCommandParser -> CreateDoctorCommand
+activate CreateDoctorCommand
+
+CreateDoctorCommand --> CreateDoctorCommandParser :
+deactivate CreateDoctorCommand
+
+CreateDoctorCommandParser --> AddressBookParser : d
+deactivate CreateDoctorCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+CreateDoctorCommandParser -[hidden]-> AddressBookParser
+destroy CreateDoctorCommandParser
+
+AddressBookParser --> LogicManager : d
+deactivate AddressBookParser
+
+LogicManager -> CreateDoctorCommand : execute(m)
+activate CreateDoctorCommand
+
+CreateDoctorCommand -> Model : addPerson(Doctor)
+activate Model
+
+Model --> CreateDoctorCommand
+deactivate Model
+
+create CommandResult
+CreateDoctorCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> CreateDoctorCommand
+deactivate CommandResult
+
+CreateDoctorCommand --> LogicManager : r
+deactivate CreateDoctorCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
+
diff --git a/docs/diagrams/CreatePatientCommand-Logic.puml b/docs/diagrams/CreatePatientCommand-Logic.puml
new file mode 100644
index 00000000000..039cd04958e
--- /dev/null
+++ b/docs/diagrams/CreatePatientCommand-Logic.puml
@@ -0,0 +1,70 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":CreatePatientCommandParser" as CreatePatientCommandParser LOGIC_COLOR
+participant "d:CreatePatientCommand" as CreatePatientCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("createPatient XXX")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("createPatient XXX")
+activate AddressBookParser
+
+create CreatePatientCommandParser
+AddressBookParser -> CreatePatientCommandParser
+activate CreatePatientCommandParser
+
+CreatePatientCommandParser --> AddressBookParser
+deactivate CreatePatientCommandParser
+
+AddressBookParser -> CreatePatientCommandParser : parse("XXX")
+activate CreatePatientCommandParser
+
+create CreatePatientCommand
+CreatePatientCommandParser -> CreatePatientCommand
+activate CreatePatientCommand
+
+CreatePatientCommand --> CreatePatientCommandParser :
+deactivate CreatePatientCommand
+
+CreatePatientCommandParser --> AddressBookParser : d
+deactivate CreatePatientCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+CreatePatientCommandParser -[hidden]-> AddressBookParser
+destroy CreatePatientCommandParser
+
+AddressBookParser --> LogicManager : d
+deactivate AddressBookParser
+
+LogicManager -> CreatePatientCommand : execute(m)
+activate CreatePatientCommand
+
+CreatePatientCommand -> Model : addPerson(Patient)
+activate Model
+
+Model --> CreatePatientCommand
+deactivate Model
+
+create CommandResult
+CreatePatientCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> CreatePatientCommand
+deactivate CommandResult
+
+CreatePatientCommand --> LogicManager : r
+deactivate CreatePatientCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeletePatientSequenceDiagram.puml
similarity index 88%
rename from docs/diagrams/DeleteSequenceDiagram.puml
rename to docs/diagrams/DeletePatientSequenceDiagram.puml
index 5241e79d7da..edd84b3cc8d 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/DeletePatientSequenceDiagram.puml
@@ -14,10 +14,10 @@ box Model MODEL_COLOR_T1
participant "m:Model" as Model MODEL_COLOR
end box
-[-> LogicManager : execute("delete 1")
+[-> LogicManager : execute("delete z/2")
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand("delete 1")
+LogicManager -> AddressBookParser : parseCommand("delete z/2")
activate AddressBookParser
create DeleteCommandParser
@@ -27,7 +27,7 @@ activate DeleteCommandParser
DeleteCommandParser --> AddressBookParser
deactivate DeleteCommandParser
-AddressBookParser -> DeleteCommandParser : parse("1")
+AddressBookParser -> DeleteCommandParser : parse("z/2")
activate DeleteCommandParser
create DeleteCommand
@@ -49,7 +49,7 @@ deactivate AddressBookParser
LogicManager -> DeleteCommand : execute(m)
activate DeleteCommand
-DeleteCommand -> Model : deletePerson(1)
+DeleteCommand -> Model : deletePerson(patient)
activate Model
Model --> DeleteCommand
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml
index 58b4f602ce6..633664d0ee4 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/LogicClassDiagram.puml
@@ -39,7 +39,7 @@ LogicManager --> Storage
Storage --[hidden] Model
Command .[hidden]up.> Storage
Command .right.> Model
-note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc
+note right of XYZCommand: XYZCommand = CreatePatientCommand, \nFindCommand, etc
Logic ..> CommandResult
LogicManager .down.> CommandResult
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index 0de5673070d..5c97083bf9d 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -15,10 +15,12 @@ Class UserPrefs
Class UniquePersonList
Class Person
Class Address
+Class Id
Class Email
Class Name
Class Phone
Class Tag
+Class Appointment
Class I #FFFFFF
}
@@ -38,10 +40,11 @@ UserPrefs .up.|> ReadOnlyUserPrefs
AddressBook *--> "1" UniquePersonList
UniquePersonList --> "~* all" Person
Person *--> Name
+Person ---> Id
Person *--> Phone
Person *--> Email
Person *--> Address
-Person *--> "*" Tag
+Person *--> "*" Appointment
Person -[hidden]up--> I
UniquePersonList -[hidden]right-> I
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml
index a821e06458c..3e58b4fa0ff 100644
--- a/docs/diagrams/StorageClassDiagram.puml
+++ b/docs/diagrams/StorageClassDiagram.puml
@@ -19,6 +19,7 @@ Class "<
>\nAddressBookStorage" as AddressBookStorage
Class JsonAddressBookStorage
Class JsonSerializableAddressBook
Class JsonAdaptedPerson
+Class JsonAdaptedAppointment
Class JsonAdaptedTag
}
@@ -39,5 +40,6 @@ JsonAddressBookStorage .up.|> AddressBookStorage
JsonAddressBookStorage ..> JsonSerializableAddressBook
JsonSerializableAddressBook --> "*" JsonAdaptedPerson
JsonAdaptedPerson --> "*" JsonAdaptedTag
+JsonAdaptedPerson --> "*" JsonAdaptedAppointment
@enduml
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index 37ad06a2803..2c73e4a651f 100644
Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png
index 02a42e35e76..7a4328a0541 100644
Binary files a/docs/images/BetterModelClassDiagram.png and b/docs/images/BetterModelClassDiagram.png differ
diff --git a/docs/images/ClearCommand-Logic.png b/docs/images/ClearCommand-Logic.png
new file mode 100644
index 00000000000..1f4743f057c
Binary files /dev/null and b/docs/images/ClearCommand-Logic.png differ
diff --git a/docs/images/CreateDoctorCommand-Logic.png b/docs/images/CreateDoctorCommand-Logic.png
new file mode 100644
index 00000000000..2741e318b6b
Binary files /dev/null and b/docs/images/CreateDoctorCommand-Logic.png differ
diff --git a/docs/images/CreatePatientCommand-Logic.png b/docs/images/CreatePatientCommand-Logic.png
new file mode 100644
index 00000000000..789bf7ccd1b
Binary files /dev/null and b/docs/images/CreatePatientCommand-Logic.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index ac2ae217c51..a16de82e6aa 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index fe91c69efe7..b8bbcd46c20 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index a19fb1b4ac8..6c39f446a11 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/StartUpPage.png b/docs/images/StartUpPage.png
new file mode 100644
index 00000000000..92c42af8da0
Binary files /dev/null and b/docs/images/StartUpPage.png differ
diff --git a/docs/images/StartUpPageSamples.png b/docs/images/StartUpPageSamples.png
new file mode 100644
index 00000000000..21db68370f7
Binary files /dev/null and b/docs/images/StartUpPageSamples.png differ
diff --git a/docs/images/clearMessage.png b/docs/images/clearMessage.png
new file mode 100644
index 00000000000..07ff01c3353
Binary files /dev/null and b/docs/images/clearMessage.png differ
diff --git a/docs/images/gui_vs_cli.png b/docs/images/gui_vs_cli.png
new file mode 100644
index 00000000000..7b722498906
Binary files /dev/null and b/docs/images/gui_vs_cli.png differ
diff --git a/docs/images/helpMessage.png b/docs/images/helpMessage.png
index b1f70470137..5cafdcc2a06 100644
Binary files a/docs/images/helpMessage.png and b/docs/images/helpMessage.png differ
diff --git a/docs/images/helpMessageUpdated.png b/docs/images/helpMessageUpdated.png
new file mode 100644
index 00000000000..c84b086e000
Binary files /dev/null and b/docs/images/helpMessageUpdated.png differ
diff --git a/docs/images/list.png b/docs/images/list.png
new file mode 100644
index 00000000000..353285b9561
Binary files /dev/null and b/docs/images/list.png differ
diff --git a/docs/images/meddict_logo.png b/docs/images/meddict_logo.png
new file mode 100644
index 00000000000..0badcc9d4d4
Binary files /dev/null and b/docs/images/meddict_logo.png differ
diff --git a/docs/images/meddict_user_guide_banner.png b/docs/images/meddict_user_guide_banner.png
new file mode 100644
index 00000000000..e69069a6ba1
Binary files /dev/null and b/docs/images/meddict_user_guide_banner.png differ
diff --git a/docs/images/photo.png b/docs/images/photo.png
new file mode 100644
index 00000000000..2959d68033d
Binary files /dev/null and b/docs/images/photo.png differ
diff --git a/docs/images/table_of_contents_banner.png b/docs/images/table_of_contents_banner.png
new file mode 100644
index 00000000000..0fab472dea0
Binary files /dev/null and b/docs/images/table_of_contents_banner.png differ
diff --git a/docs/img.png b/docs/img.png
new file mode 100644
index 00000000000..268e3c210bc
Binary files /dev/null and b/docs/img.png differ
diff --git a/docs/img_1.png b/docs/img_1.png
new file mode 100644
index 00000000000..21db68370f7
Binary files /dev/null and b/docs/img_1.png differ
diff --git a/docs/index.md b/docs/index.md
index 9e5b333ddb6..e89b19c074b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -6,7 +6,7 @@ title: MedDict
[](https://github.com/se-edu/addressbook-level3/actions)
[](https://codecov.io/gh/se-edu/addressbook-level3)
-
+
**MedDict**
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index 4c1a35fca18..ef925502437 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -36,7 +36,7 @@
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 1, 1, true);
+ public static final Version VERSION = new Version(1, 5, 0, true);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
index 126531dc862..80be775d2c2 100644
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ b/src/main/java/seedu/address/commons/core/Messages.java
@@ -4,11 +4,6 @@
* Container for user visible messages.
*/
public class Messages {
-
- public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
- public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_NO_APPOINTMENTS_FOUND = "No appointments found on this date.";
}
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/address/commons/core/index/Index.java
deleted file mode 100644
index dd170d8b68d..00000000000
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package seedu.address.commons.core.index;
-
-import seedu.address.commons.util.ToStringBuilder;
-
-/**
- * Represents a zero-based or one-based index.
- *
- * {@code Index} should be used right from the start (when parsing in a new user input), so that if the current
- * component wants to communicate with another component, it can send an {@code Index} to avoid having to know what
- * base the other component is using for its index. However, after receiving the {@code Index}, that component can
- * convert it back to an int if the index will not be passed to a different component again.
- */
-public class Index {
- private int zeroBasedIndex;
-
- /**
- * Index can only be created by calling {@link Index#fromZeroBased(int)} or
- * {@link Index#fromOneBased(int)}.
- */
- private Index(int zeroBasedIndex) {
- if (zeroBasedIndex < 0) {
- throw new IndexOutOfBoundsException();
- }
-
- this.zeroBasedIndex = zeroBasedIndex;
- }
-
- public int getZeroBased() {
- return zeroBasedIndex;
- }
-
- public int getOneBased() {
- return zeroBasedIndex + 1;
- }
-
- /**
- * Creates a new {@code Index} using a zero-based index.
- */
- public static Index fromZeroBased(int zeroBasedIndex) {
- return new Index(zeroBasedIndex);
- }
-
- /**
- * Creates a new {@code Index} using a one-based index.
- */
- public static Index fromOneBased(int oneBasedIndex) {
- return new Index(oneBasedIndex - 1);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Index)) {
- return false;
- }
-
- Index otherIndex = (Index) other;
- return zeroBasedIndex == otherIndex.zeroBasedIndex;
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this).add("zeroBasedIndex", zeroBasedIndex).toString();
- }
-}
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/address/commons/util/CollectionUtil.java
index eafe4dfd681..95b5351204c 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/address/commons/util/CollectionUtil.java
@@ -26,6 +26,17 @@ public static void requireAllNonNull(Collection> items) {
items.forEach(Objects::requireNonNull);
}
+ /**
+ * Throws IllegalArgumentException if any numbers is negative.
+ */
+ public static void requireAllPositive(int... numbers) {
+ for (int number : numbers) {
+ if (number < 0) {
+ throw new IllegalArgumentException("All numbers must be positive. Found: " + number);
+ }
+ }
+ }
+
/**
* Returns true if {@code items} contain any elements that are non-null.
*/
diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java
index 5b8359b27a8..78adb2f8d0a 100644
--- a/src/main/java/seedu/address/logic/Messages.java
+++ b/src/main/java/seedu/address/logic/Messages.java
@@ -14,16 +14,35 @@ public class Messages {
public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
- public static final String MESSAGE_INVALID_ID = "Invalid Id entered! Check the id that you have entered!";
+ public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person ID provided is invalid"
+ + " Please check and enter a new one";
+ public static final String MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX = "The patient ID provided is invalid"
+ + " Please check and enter a new one";
+ public static final String MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX = "The doctor ID provided is invalid"
+ + " Please check and enter a new one";
+ public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d person listed! "
+ + "Key in [list] to view all patients";
+ public static final String MESSAGE_INVALID_ID = "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!";
+ public static final String MESSAGE_EMPTY_REMARK = "The remark you have entered is empty! "
+ + "Please enter a valid input!";
public static final String MESSAGE_INVALID_NAME = "Invalid name entered! "
+ "Check the name that you want to search id for!\n"
- + "Key in 'list' to view all patients";
+ + "Key in [list] to view all patients";
public static final String MESSAGE_DUPLICATE_FIELDS =
"Multiple values specified for the following single-valued field(s): ";
public static final String MESSAGE_GET_ID = "The id of the person that you are finding is: %1$d";
-
+ public static final String MESSAGE_MULTIPLE_PERSONS_WITH_THE_SAME_NAME = "%1$d persons listed "
+ + "that suits your keyword!\n"
+ + "Enter more specific name keywords to retrieve the id of the person";
+ public static final String MESSAGE_MULTIPLE_PATIENT_ID =
+ "You have entered two patient IDs, which is invalid.";
+ public static final String MESSAGE_MULTIPLE_DOCTOR_ID =
+ "You have entered two doctor IDs, which is invalid.";
+ public static final String MESSAGE_MIXED_SEQUENCE_ID =
+ "You have entered a doctor ID and a patient ID in the wrong sequence.";
+ public static final String MESSAGE_COMPLETED_APPOINTMENT =
+ "The appointment is completed. Check the appointment that you want to mark!";
/**
* Returns an error message indicating the duplicate prefixes.
@@ -49,8 +68,7 @@ public static String format(Person person) {
.append(person.getEmail())
.append("; Address: ")
.append(person.getAddress())
- .append("; Tags: ");
- person.getTags().forEach(builder::append);
+ .append(";");
return builder.toString();
}
}
diff --git a/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java b/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java
index 8744882a26a..7f936892911 100644
--- a/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java
+++ b/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java
@@ -1,11 +1,17 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_MIXED_SEQUENCE_ID;
+import static seedu.address.logic.Messages.MESSAGE_MULTIPLE_DOCTOR_ID;
+import static seedu.address.logic.Messages.MESSAGE_MULTIPLE_PATIENT_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
import java.time.LocalDateTime;
+import java.util.logging.Logger;
import javafx.collections.ObservableList;
import seedu.address.logic.commands.exceptions.CommandException;
@@ -18,25 +24,24 @@
public class AddAppointmentCommand extends Command {
- public static final String COMMAND_WORD = "addAppointment";
+ public static final String COMMAND_WORD = "addA";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds an appointment with "
- + "the relevant doctor and patient. "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds an appointment for "
+ + "the relevant doctor and patient. \n"
+ COMMAND_WORD + " "
- + PREFIX_DATE + "[APPOINTMENT_TIME] "
- + PREFIX_ID + "[PATIENT_ID] "
- + PREFIX_ID + "[DOCTOR_ID] "
- + PREFIX_REMARK + "[ADDITIONAL REMARK]\n"
+ + PREFIX_ID + "PATIENT_ID "
+ + PREFIX_ID + "DOCTOR_ID "
+ + PREFIX_DATE + "DATE_TIME "
+ + PREFIX_REMARK + "[REMARK]\n"
+ "Example: " + COMMAND_WORD + " "
- + PREFIX_DATE + "2024-12-31 15:23 "
+ PREFIX_ID + "1234 "
+ PREFIX_ID + "5678 "
+ + PREFIX_DATE + "2024-12-31 15:23 "
+ PREFIX_REMARK + "third physiotherapy session";
public static final String MESSAGE_ADD_APPOINTMENT_SUCCESS = "Successfully added appointment to a patient";
- public static final String MESSAGE_PATIENT_BUSY = "The patient already has another appointment!";
- public static final String MESSAGE_DOCTOR_BUSY = "The doctor already has another appointment!";
- public static final String MESSAGE_DUPLICATE_APPOINTMENT = "The appointment already exists!";
+ public static final String MESSAGE_UNAVAILABLE_SLOT = "The patient or doctor already has another appointment!";
+ private static final Logger logger = Logger.getLogger(AddAppointmentCommand.class.getName());
private final int patientId;
private final int doctorId;
private final LocalDateTime appointmentTime;
@@ -47,8 +52,6 @@ public class AddAppointmentCommand extends Command {
*/
public AddAppointmentCommand(LocalDateTime appointmentTime, int patientId, int doctorId, String remarks) {
requireNonNull(appointmentTime);
- requireNonNull(patientId);
- requireNonNull(doctorId);
this.patientId = patientId;
this.doctorId = doctorId;
this.appointmentTime = appointmentTime;
@@ -56,19 +59,86 @@ public AddAppointmentCommand(LocalDateTime appointmentTime, int patientId, int d
}
@Override
public CommandResult execute(Model model) throws CommandException {
+ logger.info("Executing AddAppointmentCommand...");
+
requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
+ ObservableList allPersons = model.getAllPersons();
+
Person patientToAddAppointment = model.getFilteredPatientById(allPersons, patientId);
Person doctorToAddAppointment = model.getFilteredDoctorById(allPersons, doctorId);
- boolean isPatientFree = patientToAddAppointment.addAppointment(appointmentTime, patientToAddAppointment.getId(),
- doctorToAddAppointment.getId(), remarks);
- boolean isDoctorFree = doctorToAddAppointment.addAppointment(appointmentTime, patientToAddAppointment.getId(),
- doctorToAddAppointment.getId(), remarks);
+
+ checkForPersonsExistence(patientToAddAppointment, doctorToAddAppointment);
+ checkForInputId(patientId, doctorId);
+ checkForAvailability(patientToAddAppointment, doctorToAddAppointment);
+
+ logger.info(String.format("Added appointment for patient ID %d and doctor ID %d at time %s with remarks: %s",
+ patientId, doctorId, appointmentTime.toString(), remarks));
+
+ return new CommandResult(MESSAGE_ADD_APPOINTMENT_SUCCESS);
+ }
+
+ /**
+ * Checks for the existence of patient and doctor that the user enters
+ */
+ public void checkForPersonsExistence(Person patient, Person doctor) throws CommandException {
+ if (doctor == null) {
+ logger.warning(String.format("Doctor with ID %d not found.", doctorId));
+ throw new CommandException(MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX);
+ }
+
+ if (patient == null) {
+ logger.warning(String.format("Patient with ID %d not found.", patientId));
+ throw new CommandException(MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Checks that the user enters a patient's ID then a doctor ID
+ */
+ public void checkForInputId(int patientId, int doctorId) throws CommandException {
+ if (patientId % 2 == 0 && doctorId % 2 == 0) {
+ logger.warning("The user enter two patientId");
+ throw new CommandException(MESSAGE_MULTIPLE_PATIENT_ID);
+ } else if (patientId % 2 != 0 && doctorId % 2 != 0) {
+ logger.warning("The user enter two doctorId");
+ throw new CommandException(MESSAGE_MULTIPLE_DOCTOR_ID);
+ } else if (patientId % 2 != 0) {
+ logger.warning("The user enters doctorId and patientId in wrong sequence");
+ throw new CommandException(MESSAGE_MIXED_SEQUENCE_ID);
+ }
+ }
+
+ /**
+ * Checks for the availability of both patient and doctor
+ */
+ public void checkForAvailability(Person patient, Person doctor) throws CommandException {
+ boolean isPatientFree = patient.addAppointment(appointmentTime, patient.getId(),
+ doctor.getId(), remarks);
+ boolean isDoctorFree = doctor.addAppointment(appointmentTime, patient.getId(),
+ doctor.getId(), remarks);
if (!isPatientFree || !isDoctorFree) {
- throw new CommandException(MESSAGE_DUPLICATE_APPOINTMENT);
+ throw new CommandException(MESSAGE_UNAVAILABLE_SLOT);
}
+ }
- return new CommandResult(MESSAGE_ADD_APPOINTMENT_SUCCESS);
+ @Override
+ public boolean equals(Object other) {
+ // Short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof AddAppointmentCommand)) {
+ return false;
+ }
+
+ // State check
+ AddAppointmentCommand otherCommand = (AddAppointmentCommand) other;
+ return appointmentTime.equals(otherCommand.appointmentTime)
+ && patientId == otherCommand.patientId
+ && doctorId == otherCommand.doctorId
+ && remarks.equals(otherCommand.remarks);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/AddNotesCommand.java b/src/main/java/seedu/address/logic/commands/AddNotesCommand.java
deleted file mode 100644
index b2fe07070fe..00000000000
--- a/src/main/java/seedu/address/logic/commands/AddNotesCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import javafx.collections.ObservableList;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-
-
-/**
- * Adds notes to a Patient's remarks
- */
-public class AddNotesCommand extends Command {
-
- public static final String COMMAND_WORD = "addNotes";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds notes to the remarks of a Patient."
- + "Existing remarks will be concatenated by the input.\n"
- + COMMAND_WORD + " "
- + PREFIX_ID + "[PATIENT_ID] "
- + PREFIX_REMARK + "[ADDITIONAL REMARKS]\n"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_ID + "1234 "
- + PREFIX_REMARK + "Much better than previous appointment.";
-
- public static final String MESSAGE_ADD_NOTES_SUCCESS = "Successfully "
- + "added notes: %s to patient of ID: %d.";
- private final int patientId;
- private final String additionalNotes;
-
- /**
- * Adds notes to a Patient's remarks
- * @param patientId patient id
- * @param additionalNotes notes to be added
- */
- public AddNotesCommand(int patientId, String additionalNotes) {
- requireAllNonNull(patientId, additionalNotes);
-
- this.patientId = patientId;
- this.additionalNotes = additionalNotes;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
-
- requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
- Person patientToAddNotes = model.getFilteredPatientById(allPersons, patientId);
- patientToAddNotes.addNotes(additionalNotes);
-
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
-
- return new CommandResult(String.format(MESSAGE_ADD_NOTES_SUCCESS, additionalNotes, patientId
- ));
- }
-
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddRemarksCommand.java b/src/main/java/seedu/address/logic/commands/AddRemarksCommand.java
new file mode 100644
index 00000000000..48fed53dc63
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/AddRemarksCommand.java
@@ -0,0 +1,111 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import javafx.collections.ObservableList;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Remark;
+
+
+/**
+ * Adds remarks to a Patient's remarks
+ */
+public class AddRemarksCommand extends Command {
+
+ public static final String COMMAND_WORD = "addR";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds remarks to the patient. "
+ + "Existing remarks will be concatenated by the input.\n"
+ + COMMAND_WORD + " "
+ + PREFIX_ID + "PATIENT_ID "
+ + PREFIX_REMARK + "REMARK\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_ID + "1234 "
+ + PREFIX_REMARK + "Much better than previous appointment.";
+
+ public static final String MESSAGE_ADD_REMARKS_SUCCESS = "Successfully "
+ + "added remarks: '%s' to patient of ID: %d.";
+ public static final String MESSAGE_ADD_REMARKS_FAILURE = "Unable to "
+ + "add remarks! Check the id entered!";
+ public static final String MESSAGE_WRONG_ROLE = "Unable to add remarks for a doctor.\n"
+ + " Please check the id of the person you are adding remarks to!";
+ private final int patientId;
+ private final Remark additionalRemarks;
+
+ /**
+ * Adds notes to a Patient's remarks
+ * @param patientId patient id
+ * @param remarks additional remarks to be added
+ */
+ public AddRemarksCommand(int patientId, Remark remarks) {
+ requireAllNonNull(remarks);
+ this.patientId = patientId;
+ this.additionalRemarks = remarks;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+
+ requireNonNull(model);
+ ObservableList allPersons = model.getAllPersons();
+ Person patientToAddRemarks = model.getFilteredPatientById(allPersons, patientId);
+
+ checkForCorrectPatient(patientToAddRemarks);
+
+ Person editedPatient = createUpdatedRemarksPatient(patientToAddRemarks);
+
+ model.setPerson(patientToAddRemarks, editedPatient);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(String.format(MESSAGE_ADD_REMARKS_SUCCESS,
+ additionalRemarks, patientId
+ ));
+ }
+
+ /**
+ * Checks for valid patient input
+ */
+ public void checkForCorrectPatient(Person patient) throws CommandException {
+ if (patient == null) {
+ throw new CommandException(MESSAGE_ADD_REMARKS_FAILURE);
+ }
+ if (patient.getRole().equals("DOCTOR")) {
+ throw new CommandException(MESSAGE_WRONG_ROLE);
+ }
+ }
+
+ /**
+ * Creates a copy of the original patient with remarks being updated
+ */
+ public Person createUpdatedRemarksPatient(Person patientToAddRemarks) {
+ return new Person(patientToAddRemarks.getName(),
+ patientToAddRemarks.getId(), patientToAddRemarks.getRole(), patientToAddRemarks.getPhone(),
+ patientToAddRemarks.getEmail(), patientToAddRemarks.getAddress(),
+ patientToAddRemarks.addRemarks(additionalRemarks.getValue()),
+ patientToAddRemarks.getAppointments());
+ }
+ @Override
+ public boolean equals(Object other) {
+ // Shortcuts: reference equality
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof check and cast
+ if (!(other instanceof AddRemarksCommand)) {
+ return false;
+ }
+
+ AddRemarksCommand otherCommand = (AddRemarksCommand) other;
+
+ // Compare patientId and additionalNotes
+ return patientId == otherCommand.patientId
+ && additionalRemarks.equals(otherCommand.additionalRemarks);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/CheckAppointmentCommand.java b/src/main/java/seedu/address/logic/commands/CheckAppointmentCommand.java
index 300616b7e82..f5df78f188f 100644
--- a/src/main/java/seedu/address/logic/commands/CheckAppointmentCommand.java
+++ b/src/main/java/seedu/address/logic/commands/CheckAppointmentCommand.java
@@ -7,7 +7,7 @@
import java.time.LocalDate;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.Messages;
+import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Person;
@@ -17,18 +17,20 @@
*/
public class CheckAppointmentCommand extends Command {
- public static final String COMMAND_WORD = "checkAppointment";
+ public static final String COMMAND_WORD = "checkA";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Checks the appointments of the doctor identified "
- + "by the doctor ID. "
- + "Parameters: DOCTOR_ID (must be a valid ID) "
- + "LOCAL_DATETIME \n"
- + "Example: " + COMMAND_WORD + " " + PREFIX_ID + " 01" + PREFIX_DAY_DATE + " 2023-09-25";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Checks the appointments of the patient/doctor identified "
+ + "based on id provided. \n"
+ + COMMAND_WORD + " "
+ + PREFIX_ID + "ID "
+ + PREFIX_DAY_DATE + "DATE \n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_ID + "01 " + PREFIX_DAY_DATE + "2023-09-25";
- public static final String MESSAGE_CHECK_APPOINTMENT_SUCCESS = "Checked appointment for Doctor: %1$s on %2$s";
- public static final String MESSAGE_NO_APPOINTMENT_FOUND = "No appointment found for Doctor: %1$s on %2$s";
- public static final String MESSAGE_NO_DATE_TIME = "No date time is given for Doctor appointment: %1$s on %2$s";
+ public static final String MESSAGE_NO_APPOINTMENT_FOUND = "No appointment found for the person: %s";
+
+ public static final String MESSAGE_NO_DATE_TIME = "No date time is given for appointment: %s";
private final int doctorId;
private final LocalDate date;
@@ -38,7 +40,7 @@ public class CheckAppointmentCommand extends Command {
* @param date the specific date and time of the appointment to check (optional)
*/
public CheckAppointmentCommand(int doctorId, LocalDate date) {
- requireNonNull(doctorId); // Only patientId is mandatory
+ requireNonNull(doctorId);
this.doctorId = doctorId;
this.date = date;
}
@@ -47,12 +49,11 @@ public CheckAppointmentCommand(int doctorId, LocalDate date) {
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
+ ObservableList allPersons = model.getAllPersons();
Person doctorToCheckAppointment = model.getFilteredDoctorById(allPersons, doctorId);
if (doctorToCheckAppointment == null) {
- // Throw an exception if the doctor is not found
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ throw new CommandException(Messages.MESSAGE_INVALID_ID);
}
if (date == null) {
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
index 9c86b1fa6e4..3cf4d451b53 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java
@@ -4,6 +4,7 @@
import seedu.address.model.AddressBook;
import seedu.address.model.Model;
+import seedu.address.model.person.Id;
/**
* Clears the address book.
@@ -11,13 +12,15 @@
public class ClearCommand extends Command {
public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
+ public static final String MESSAGE_SUCCESS = "MedDict has been cleared!";
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.setAddressBook(new AddressBook());
+ Id.resetDoctorIdCounter();
+ Id.resetPatientIdCounter();
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/CreateDoctorCommand.java b/src/main/java/seedu/address/logic/commands/CreateDoctorCommand.java
index dffd2d3c564..6340612462e 100644
--- a/src/main/java/seedu/address/logic/commands/CreateDoctorCommand.java
+++ b/src/main/java/seedu/address/logic/commands/CreateDoctorCommand.java
@@ -6,38 +6,43 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import java.util.Objects;
+
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
+import seedu.address.model.person.Id;
import seedu.address.model.person.Person;
-
/**
* Creates a new Doctor profile
- *
- * Code is adapted from @@author sandyk0105
*/
public class CreateDoctorCommand extends Command {
- public static final String COMMAND_WORD = "createDoctor";
+ //@author Nigeltzy-reused
+ //Reused from @@author sandyk0105's code with minor modifications
+ public static final String COMMAND_WORD = "createD";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a new doctor. "
- + "Parameters: "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a new doctor. \n"
+ + COMMAND_WORD + " "
+ PREFIX_NAME + "NAME "
+ PREFIX_PHONE + "PHONE "
+ PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
+ + PREFIX_ADDRESS + "ADDRESS \n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_NAME + "John Doe "
+ PREFIX_PHONE + "98765432 "
+ PREFIX_EMAIL + "johnd@example.com "
+ PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 ";
- public static final String MESSAGE_SUCCESS = "Successfully created a new doctor Doctor#%d : %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This doctor already exists";
+ public static final String MESSAGE_SUCCESS = "Successfully created a new doctor of ID: #%d : \n"
+ + "%2$s";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This doctor already exists.";
+ public static final String MESSAGE_OVERLAPPING_PATIENT = "This person already exists as a patient\n"
+ + "Please check the details you have entered!";
private final Person toAdd;
/**
- * Creates an CreatevCommand to add the specified {@code doctor}
+ * Creates an CreateDoctorCommand to add the specified {@code doctor}
*/
public CreateDoctorCommand(Person doctor) {
requireNonNull(doctor);
@@ -49,11 +54,43 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ if (model.getPersonRole(toAdd).equals("DOCTOR")) {
+ if (toAdd.getId() == Id.getCurrentDoctorIdCounter() - 2) {
+ Id.reduceCurrentDoctorIdCounter();
+ }
+ throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ }
+ if (model.getPersonRole(toAdd).equals("PATIENT")) {
+ if (toAdd.getId() == Id.getCurrentDoctorIdCounter() - 2) {
+ Id.reduceCurrentDoctorIdCounter();
+ }
+ throw new CommandException(MESSAGE_OVERLAPPING_PATIENT);
+ }
}
model.addPerson(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd.getId(), Messages.format(toAdd)));
}
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof CreateDoctorCommand)) {
+ return false;
+ }
+
+ CreateDoctorCommand otherCmd = (CreateDoctorCommand) other;
+ return otherCmd.toAdd.equals(this.toAdd);
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(toAdd);
+ }
+ //@@author
+
}
diff --git a/src/main/java/seedu/address/logic/commands/CreatePatientCommand.java b/src/main/java/seedu/address/logic/commands/CreatePatientCommand.java
index 61b1288c35d..d09c5c50b98 100644
--- a/src/main/java/seedu/address/logic/commands/CreatePatientCommand.java
+++ b/src/main/java/seedu/address/logic/commands/CreatePatientCommand.java
@@ -6,31 +6,37 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import java.util.Objects;
+
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
+import seedu.address.model.person.Id;
import seedu.address.model.person.Person;
/**
* Creates a new Patient profile
*/
public class CreatePatientCommand extends Command {
- public static final String COMMAND_WORD = "createPatient";
+ public static final String COMMAND_WORD = "createP";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a new patient. "
- + "Parameters: "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a new patient. \n"
+ + COMMAND_WORD + " "
+ PREFIX_NAME + "NAME "
+ PREFIX_PHONE + "PHONE "
+ PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
+ + PREFIX_ADDRESS + "ADDRESS \n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_NAME + "John Doe "
+ PREFIX_PHONE + "98765432 "
+ PREFIX_EMAIL + "johnd@example.com "
+ PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 ";
- public static final String MESSAGE_SUCCESS = "Successfully created a new patient Patient#%d : %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This patient already exists";
+ public static final String MESSAGE_SUCCESS = "Successfully created a new patient of ID: #%d : \n"
+ + "%2$s";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This patient already exists.";
+ public static final String MESSAGE_OVERLAPPING_DOCTOR = "This person already exists as a doctor!\n"
+ + "Please check the details you have entered!";
private final Person toAdd;
@@ -47,11 +53,42 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ if (model.getPersonRole(toAdd).equals("PATIENT")) {
+ if (toAdd.getId() == Id.getCurrentPatientIdCounter() - 2) {
+ Id.reduceCurrentPatientIdCounter();
+ }
+ throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ }
+ if (model.getPersonRole(toAdd).equals("DOCTOR")) {
+ if (toAdd.getId() == Id.getCurrentPatientIdCounter() - 2) {
+ Id.reduceCurrentPatientIdCounter();
+ }
+ throw new CommandException(MESSAGE_OVERLAPPING_DOCTOR);
+ }
}
model.addPerson(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd.getId(), Messages.format(toAdd)));
}
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof CreatePatientCommand)) {
+ return false;
+ }
+
+ CreatePatientCommand otherCmd = (CreatePatientCommand) other;
+ return otherCmd.toAdd.equals(this.toAdd);
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(toAdd);
+ }
+
}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteAppointmentCommand.java b/src/main/java/seedu/address/logic/commands/DeleteAppointmentCommand.java
index 1d91e0740a2..59f685185e7 100644
--- a/src/main/java/seedu/address/logic/commands/DeleteAppointmentCommand.java
+++ b/src/main/java/seedu/address/logic/commands/DeleteAppointmentCommand.java
@@ -1,11 +1,14 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
import java.time.LocalDateTime;
+import java.util.logging.Logger;
import javafx.collections.ObservableList;
import seedu.address.logic.commands.exceptions.CommandException;
@@ -16,21 +19,23 @@
* deletes an appointment to both a patient and a doctor.
*/
public class DeleteAppointmentCommand extends Command {
- public static final String COMMAND_WORD = "deleteAppointment";
+ public static final String COMMAND_WORD = "deleteA";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": deletes an appointment "
- + "between the relevant doctor and patient. "
+ + "between the relevant doctor and patient.\n"
+ COMMAND_WORD + " "
- + PREFIX_DATE + "[APPOINTMENT_TIME] "
- + PREFIX_ID + "[PATIENT_ID] "
- + PREFIX_ID + "[DOCTOR_ID]\n"
+ + PREFIX_ID + "PATIENT_ID "
+ + PREFIX_ID + "DOCTOR_ID "
+ + PREFIX_DATE + "DATE_TIME \n"
+ "Example: " + COMMAND_WORD + " "
- + PREFIX_DATE + "2024-12-31 15:23 "
+ PREFIX_ID + "1234 "
- + PREFIX_ID + "5678";
+ + PREFIX_ID + "5678 "
+ + PREFIX_DATE + "2024-12-31 15:23";
public static final String MESSAGE_DELETE_APPOINTMENT_SUCCESS = "Successfully "
+ "deleted appointment to a patient";
- public static final String MESSAGE_DELETE_APPOINTMENT_FAIL = "The appointment doesn't exist!";
+ public static final String MESSAGE_DELETE_APPOINTMENT_FAIL = "The appointment doesn't exist! "
+ + "Please check again the details you have entered!";
+ private static final Logger logger = Logger.getLogger(DeleteAppointmentCommand.class.getName());
private final int patientId;
private final int doctorId;
private final LocalDateTime appointmentTime;
@@ -39,6 +44,7 @@ public class DeleteAppointmentCommand extends Command {
* Creates an DeleteAppointmentCommand to add the specified patient and doctor ids
*/
public DeleteAppointmentCommand(LocalDateTime appointmentTime, int patientId, int doctorId) {
+ requireNonNull(appointmentTime);
this.patientId = patientId;
this.doctorId = doctorId;
this.appointmentTime = appointmentTime;
@@ -46,9 +52,18 @@ public DeleteAppointmentCommand(LocalDateTime appointmentTime, int patientId, in
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
+ ObservableList allPersons = model.getAllPersons();
Person patientToAddAppointment = model.getFilteredPatientById(allPersons, patientId);
Person doctorToAddAppointment = model.getFilteredDoctorById(allPersons, doctorId);
+
+ if (doctorToAddAppointment == null) {
+ logger.warning(String.format("Doctor with ID %d not found.", doctorId));
+ throw new CommandException(MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX);
+ }
+ if (patientToAddAppointment == null) {
+ logger.warning(String.format("Patient with ID %d not found.", patientId));
+ throw new CommandException(MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX);
+ }
boolean isDeleteSuccessful = patientToAddAppointment.deleteAppointment(appointmentTime,
patientToAddAppointment.getId(),
doctorToAddAppointment.getId());
@@ -60,4 +75,23 @@ public CommandResult execute(Model model) throws CommandException {
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
return new CommandResult(MESSAGE_DELETE_APPOINTMENT_SUCCESS);
}
+
+ @Override
+ public boolean equals(Object other) {
+ // Short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof DeleteAppointmentCommand)) {
+ return false;
+ }
+
+ // State check
+ DeleteAppointmentCommand otherCommand = (DeleteAppointmentCommand) other;
+ return appointmentTime.equals(otherCommand.appointmentTime)
+ && patientId == otherCommand.patientId
+ && doctorId == otherCommand.doctorId;
+ }
}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
new file mode 100644
index 00000000000..90c1efd6ded
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
@@ -0,0 +1,80 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
+
+import javafx.collections.ObservableList;
+import seedu.address.commons.util.ToStringBuilder;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.person.Id;
+import seedu.address.model.person.Person;
+
+/**
+ * Deletes a person identified using it's displayed index from the address book.
+ */
+public class DeleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "delete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": deletes a Person (Patient/Doctor) "
+ + "based on id provided.\n"
+ + COMMAND_WORD + " "
+ + PREFIX_ID + "ID \n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_ID + "1234";
+
+ public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Successfully "
+ + "deleted a person";
+ public static final String MESSAGE_DELETE_PERSON_FAILURE = "Unable to "
+ + "delete the person, check the ID entered!";
+ private final int personId;
+
+ public DeleteCommand(int personId) {
+ this.personId = personId;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ ObservableList allPersons = model.getAllPersons();
+
+ Person personToDelete = model.getFilteredPatientById(allPersons, personId);
+ if (personToDelete == null) {
+ throw new CommandException(MESSAGE_DELETE_PERSON_FAILURE);
+ }
+ personToDelete.deleteAllAppointments(model);
+ model.deletePerson(personToDelete);
+ if (personId == Id.getCurrentPatientIdCounter() - 2) {
+ Id.reduceCurrentPatientIdCounter();
+ }
+ if (personId == Id.getCurrentDoctorIdCounter() - 2) {
+ Id.reduceCurrentDoctorIdCounter();
+ }
+ return new CommandResult(MESSAGE_DELETE_PERSON_SUCCESS);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof DeleteCommand)) {
+ return false;
+ }
+
+ DeleteCommand otherDeleteCommand = (DeleteCommand) other;
+ return personId == otherDeleteCommand.personId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .add("person Id", personId)
+ .toString();
+ }
+}
+
diff --git a/src/main/java/seedu/address/logic/commands/DeletePatientCommand.java b/src/main/java/seedu/address/logic/commands/DeletePatientCommand.java
deleted file mode 100644
index 29a0f08c3a4..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeletePatientCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.util.ToStringBuilder;
-import seedu.address.logic.Messages;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeletePatientCommand extends Command {
-
- public static final String COMMAND_WORD = "deletePatient";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": deletes a patient. "
- + COMMAND_WORD + " "
- + PREFIX_ID + "[PATIENT_ID]"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_ID + "1234";
-
- public static final String MESSAGE_DELETE_PATIENT_SUCCESS = "Successfully "
- + "deleted a patient";;
-
- private final int patientId;
-
- public DeletePatientCommand(int patientId) {
- this.patientId = patientId;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
-
- ObservableList allPersons = model.getFilteredPersonList();
-
- Person patientToDelete = model.getFilteredPatientById(allPersons, patientId);
- model.deletePerson(patientToDelete);
-
- return new CommandResult(String.format(MESSAGE_DELETE_PATIENT_SUCCESS, Messages.format(patientToDelete)));
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this)
- .add("patientId", patientId)
- .toString();
- }
-}
-
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
index 8615de6db93..01a9491dca5 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/EditCommand.java
@@ -3,31 +3,28 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
-import seedu.address.commons.core.index.Index;
+import javafx.collections.ObservableList;
import seedu.address.commons.util.CollectionUtil;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Address;
+import seedu.address.model.person.Appointment;
import seedu.address.model.person.Email;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.person.Remark;
-import seedu.address.model.tag.Tag;
/**
@@ -38,47 +35,47 @@ public class EditCommand extends Command {
public static final String COMMAND_WORD = "edit";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
- + "by the index number used in the displayed person list. "
+ + "by the ID of the person. \n"
+ "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
+ + COMMAND_WORD + " "
+ + PREFIX_ID + "ID "
+ "[" + PREFIX_NAME + "NAME] "
- + "[" + PREFIX_PHONE + "PHONE] "
+ + "[" + PREFIX_PHONE + "PHONE_NUMBER] "
+ "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
+ + "[" + PREFIX_ADDRESS + "ADDRESS] \n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_ID + "1 "
+ PREFIX_PHONE + "91234567 "
+ PREFIX_EMAIL + "johndoe@example.com";
public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s";
public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book.";
+ public static final String MESSAGE_EDIT_FAILURE = "Unable to "
+ + "find the person! Check the ID entered!";
- private final Index index;
private final EditPersonDescriptor editPersonDescriptor;
+ private final int idToEdit;
/**
- * @param index of the person in the filtered person list to edit
+ * @param id of the person in the filtered person list to edit
* @param editPersonDescriptor details to edit the person with
*/
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
- requireNonNull(index);
+ public EditCommand(int id, EditPersonDescriptor editPersonDescriptor) {
requireNonNull(editPersonDescriptor);
- this.index = index;
+ this.idToEdit = id;
this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
}
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ ObservableList allPersons = model.getAllPersons();
+ Person personToEdit = model.getFilteredPatientById(allPersons, idToEdit);
+ if (personToEdit == null) {
+ throw new CommandException(MESSAGE_EDIT_FAILURE);
}
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
@@ -98,13 +95,14 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript
assert personToEdit != null;
Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
+ int personId = personToEdit.getId();
Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
- Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
Remark updatedRemark = personToEdit.getRemark();
- return new Person(updatedName, personToEdit.getRole(),
- updatedPhone, updatedEmail, updatedAddress, updatedRemark, updatedTags);
+ List appointments = personToEdit.getAppointments();
+ return new Person(updatedName, personId, personToEdit.getRole(),
+ updatedPhone, updatedEmail, updatedAddress, updatedRemark, appointments);
}
@Override
@@ -119,14 +117,13 @@ public boolean equals(Object other) {
}
EditCommand otherEditCommand = (EditCommand) other;
- return index.equals(otherEditCommand.index)
+ return idToEdit == otherEditCommand.idToEdit
&& editPersonDescriptor.equals(otherEditCommand.editPersonDescriptor);
}
@Override
public String toString() {
return new ToStringBuilder(this)
- .add("index", index)
.add("editPersonDescriptor", editPersonDescriptor)
.toString();
}
@@ -137,30 +134,30 @@ public String toString() {
*/
public static class EditPersonDescriptor {
private Name name;
+ private int id;
private Phone phone;
private Email email;
private Address address;
- private Set tags;
+ private Remark remarks;
public EditPersonDescriptor() {}
/**
* Copy constructor.
- * A defensive copy of {@code tags} is used internally.
*/
public EditPersonDescriptor(EditPersonDescriptor toCopy) {
setName(toCopy.name);
setPhone(toCopy.phone);
setEmail(toCopy.email);
setAddress(toCopy.address);
- setTags(toCopy.tags);
+ setRemark(toCopy.remarks);
}
/**
* Returns true if at least one field is edited.
*/
public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
+ return CollectionUtil.isAnyNonNull(name, phone, email, address);
}
public void setName(Name name) {
@@ -170,7 +167,12 @@ public void setName(Name name) {
public Optional getName() {
return Optional.ofNullable(name);
}
-
+ public void setId(int id) {
+ this.id = id;
+ }
+ public int getId() {
+ return id;
+ }
public void setPhone(Phone phone) {
this.phone = phone;
}
@@ -194,24 +196,15 @@ public void setAddress(Address address) {
public Optional getAddress() {
return Optional.ofNullable(address);
}
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
+ public void setRemark(Remark remarks) {
+ this.remarks = remarks;
}
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
+ public Optional getRemarks() {
+ return Optional.ofNullable(remarks);
}
+
@Override
public boolean equals(Object other) {
if (other == this) {
@@ -228,7 +221,7 @@ public boolean equals(Object other) {
&& Objects.equals(phone, otherEditPersonDescriptor.phone)
&& Objects.equals(email, otherEditPersonDescriptor.email)
&& Objects.equals(address, otherEditPersonDescriptor.address)
- && Objects.equals(tags, otherEditPersonDescriptor.tags);
+ && Objects.equals(remarks, otherEditPersonDescriptor.remarks);
}
@Override
@@ -238,7 +231,7 @@ public String toString() {
.add("phone", phone)
.add("email", email)
.add("address", address)
- .add("tags", tags)
+ .add("remarks", remarks)
.toString();
}
}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java
index 3dd85a8ba90..6c5c48fde90 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java
@@ -8,8 +8,7 @@
public class ExitCommand extends Command {
public static final String COMMAND_WORD = "exit";
-
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting MedDict as requested ...";
@Override
public CommandResult execute(Model model) {
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
index 72b9eddd3a7..2f7803c675d 100644
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ b/src/main/java/seedu/address/logic/commands/FindCommand.java
@@ -16,8 +16,8 @@ public class FindCommand extends Command {
public static final String COMMAND_WORD = "find";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "the specified keywords (case-insensitive).\n"
+ + COMMAND_WORD + " KEYWORDS \n"
+ "Example: " + COMMAND_WORD + " alice bob charlie";
private final NameContainsKeywordsPredicate predicate;
@@ -30,6 +30,13 @@ public FindCommand(NameContainsKeywordsPredicate predicate) {
public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredPersonList(predicate);
+ if (model.getFilteredPersonList().isEmpty()) {
+ return new CommandResult(Messages.MESSAGE_INVALID_NAME);
+ }
+ if (model.getFilteredPersonList().size() > 1) {
+ return new CommandResult(String.format(Messages.MESSAGE_MULTIPLE_PERSONS_WITH_THE_SAME_NAME,
+ model.getFilteredPersonList().size()));
+ }
return new CommandResult(
String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
}
diff --git a/src/main/java/seedu/address/logic/commands/GetIdCommand.java b/src/main/java/seedu/address/logic/commands/GetIdCommand.java
index f4ac634b4e9..178fe0ed30a 100644
--- a/src/main/java/seedu/address/logic/commands/GetIdCommand.java
+++ b/src/main/java/seedu/address/logic/commands/GetIdCommand.java
@@ -13,12 +13,12 @@
* Keyword matching is case-insensitive.
*/
public class GetIdCommand extends Command {
- public static final String COMMAND_WORD = "getId";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": gets the id "
- + "of a patient based on the name provided. "
- + COMMAND_WORD + "[KEYWORDS...]\n"
+ public static final String COMMAND_WORD = "get";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": gets the ID "
+ + "of a patient based on the name provided. \n"
+ + COMMAND_WORD + " KEYWORDS\n"
+ "Example: " + COMMAND_WORD
- + "John Philips";
+ + " John Philips";
private final NameContainsKeywordsPredicate predicate;
public GetIdCommand(NameContainsKeywordsPredicate predicate) {
this.predicate = predicate;
@@ -30,6 +30,10 @@ public CommandResult execute(Model model) {
if (model.getFilteredPersonList().isEmpty()) {
return new CommandResult(Messages.MESSAGE_INVALID_NAME);
}
+ if (model.getFilteredPersonList().size() > 1) {
+ return new CommandResult(String.format(Messages.MESSAGE_MULTIPLE_PERSONS_WITH_THE_SAME_NAME,
+ model.getFilteredPersonList().size()));
+ }
return new CommandResult(String.format(Messages.MESSAGE_GET_ID,
model.getFilteredPersonList().get(0).getId()));
diff --git a/src/main/java/seedu/address/logic/commands/MarkAppointmentCommand.java b/src/main/java/seedu/address/logic/commands/MarkAppointmentCommand.java
index 16c21cc9a2f..81542a5f972 100644
--- a/src/main/java/seedu/address/logic/commands/MarkAppointmentCommand.java
+++ b/src/main/java/seedu/address/logic/commands/MarkAppointmentCommand.java
@@ -1,6 +1,11 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_MIXED_SEQUENCE_ID;
+import static seedu.address.logic.Messages.MESSAGE_MULTIPLE_DOCTOR_ID;
+import static seedu.address.logic.Messages.MESSAGE_MULTIPLE_PATIENT_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
@@ -16,21 +21,20 @@
* marks an appointment as complete.
*/
public class MarkAppointmentCommand extends Command {
- public static final String COMMAND_WORD = "markAppointment";
+ public static final String COMMAND_WORD = "mark";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": marks an appointment as complete"
- + "between the relevant doctor and patient. "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Marks an appointment of a doctor "
+ + "with a patient as complete. \n"
+ COMMAND_WORD + " "
- + PREFIX_DATE + "[APPOINTMENT_TIME] "
- + PREFIX_ID + "[PATIENT_ID] "
- + PREFIX_ID + "[DOCTOR_ID]\n"
+ + PREFIX_ID + "PATIENT_ID "
+ + PREFIX_ID + "DOCTOR_ID "
+ + PREFIX_DATE + "DATE_TIME \n"
+ "Example: " + COMMAND_WORD + " "
- + PREFIX_DATE + "2024-12-31 15:23 "
+ PREFIX_ID + "1234 "
- + PREFIX_ID + "5678";
+ + PREFIX_ID + "5678 "
+ + PREFIX_DATE + "2024-12-31 15:23";
public static final String MESSAGE_MARK_APPOINTMENT_SUCCESS = "Successfully "
+ "marked appointment as complete";
- public static final String MESSAGE_MARK_APPOINTMENT_FAIL = "The appointment doesn't exist!";
private final int patientId;
private final int doctorId;
private final LocalDateTime appointmentTime;
@@ -50,16 +54,17 @@ public MarkAppointmentCommand(LocalDateTime appointmentTime, int patientId, int
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
+ ObservableList allPersons = model.getAllPersons();
Person patientToMarkAppointment = model.getFilteredPatientById(allPersons, patientId);
Person doctorToMarkAppointment = model.getFilteredDoctorById(allPersons, doctorId);
- boolean isMarkSuccessful = patientToMarkAppointment.markAppointment(appointmentTime,
+ checkForExistenceOfPersons(patientToMarkAppointment, doctorToMarkAppointment);
+ checkForValidIds(patientId, doctorId);
+
+ patientToMarkAppointment.markAppointment(appointmentTime,
patientToMarkAppointment.getId(),
doctorToMarkAppointment.getId());
- if (!isMarkSuccessful) {
- throw new CommandException(MESSAGE_MARK_APPOINTMENT_FAIL);
- }
+
doctorToMarkAppointment.markAppointment(appointmentTime, patientToMarkAppointment.getId(),
doctorToMarkAppointment.getId());
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
@@ -68,4 +73,47 @@ public CommandResult execute(Model model) throws CommandException {
}
+ /**
+ * Checks for the existence of patient and doctor that the user enters
+ */
+ public void checkForExistenceOfPersons(Person patient, Person doctor) throws CommandException {
+ if (doctor == null) {
+ throw new CommandException(MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX);
+ }
+ if (patient == null) {
+ throw new CommandException(MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Checks that the user enters a patient's ID then a doctor ID
+ */
+ public void checkForValidIds(int patientId, int doctorId) throws CommandException {
+ if (patientId % 2 == 0 && doctorId % 2 == 0) {
+ throw new CommandException(MESSAGE_MULTIPLE_PATIENT_ID);
+ } else if (patientId % 2 != 0 && doctorId % 2 != 0) {
+ throw new CommandException(MESSAGE_MULTIPLE_DOCTOR_ID);
+ } else if (patientId % 2 != 0) {
+ throw new CommandException(MESSAGE_MIXED_SEQUENCE_ID);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // Short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof MarkAppointmentCommand)) {
+ return false;
+ }
+
+ // State check
+ MarkAppointmentCommand otherCommand = (MarkAppointmentCommand) other;
+ return appointmentTime.equals(otherCommand.appointmentTime)
+ && patientId == otherCommand.patientId
+ && doctorId == otherCommand.doctorId;
+ }
}
diff --git a/src/main/java/seedu/address/logic/commands/RemarkCommand.java b/src/main/java/seedu/address/logic/commands/RemarkCommand.java
deleted file mode 100644
index 28312734731..00000000000
--- a/src/main/java/seedu/address/logic/commands/RemarkCommand.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Remark;
-
-/**
- * Changes the remark of an existing person in the address book.
- */
-public class RemarkCommand extends Command {
-
- public static final String COMMAND_WORD = "remark";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the person identified "
- + "by the index number used in the last person listing. "
- + "Existing remark will be overwritten by the input.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + PREFIX_REMARK + "[REMARK]\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + PREFIX_REMARK + "Likes to swim.";
-
- public static final String MESSAGE_ADD_REMARK_SUCCESS = "Added remark to Person: %1$s";
- public static final String MESSAGE_DELETE_REMARK_SUCCESS = "Removed remark from Person: %1$s";
-
- private final Index index;
- private final Remark remark;
-
- /**
- * @param index of the person in the filtered person list to edit the remark
- * @param remark of the person to be updated to
- */
- public RemarkCommand(Index index, Remark remark) {
- requireAllNonNull(index, remark);
-
- this.index = index;
- this.remark = remark;
- }
- @Override
- public CommandResult execute(Model model) throws CommandException {
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = new Person(personToEdit.getName(),
- personToEdit.getRole(), personToEdit.getPhone(), personToEdit.getEmail(),
- personToEdit.getAddress(), remark, personToEdit.getTags());
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
-
- return new CommandResult(generateSuccessMessage(editedPerson));
- }
-
- /**
- * Generates a command execution success message based on whether the remark is added to or removed from
- * {@code personToEdit}.
- */
- private String generateSuccessMessage(Person personToEdit) {
- String message = !remark.getValue().isEmpty() ? MESSAGE_ADD_REMARK_SUCCESS : MESSAGE_DELETE_REMARK_SUCCESS;
- return String.format(message, personToEdit);
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof RemarkCommand)) {
- return false;
- }
-
- // state check
- RemarkCommand e = (RemarkCommand) other;
- return index.equals(e.index)
- && remark.equals(e.remark);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ViewHistoryCommand.java b/src/main/java/seedu/address/logic/commands/ViewHistoryCommand.java
index 0344ab28950..037b474fe84 100644
--- a/src/main/java/seedu/address/logic/commands/ViewHistoryCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ViewHistoryCommand.java
@@ -7,7 +7,7 @@
import java.time.LocalDateTime;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.Messages;
+import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Person;
@@ -17,14 +17,16 @@
*/
public class ViewHistoryCommand extends Command {
- public static final String COMMAND_WORD = "viewHistory";
+ public static final String COMMAND_WORD = "view";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Views the medical history of the patient identified "
- + "by the patient ID. "
- + "Parameters: PATIENT_ID (must be a valid ID) "
- + "LOCAL_DATETIME \n"
- + "Example: " + COMMAND_WORD + " " + PREFIX_ID + "01" + PREFIX_DATE + "2023-09-25 10:15";
- public static final String MESSAGE_NO_HISTORY_FOUND = "No history found for Patient";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Views the medical history of a patient/doctor "
+ + "based on ID provided. \n"
+ + COMMAND_WORD + " "
+ + PREFIX_ID + "PATIENT_ID "
+ + "[" + PREFIX_DATE + "DATE_TIME] \n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_ID + "01 " + PREFIX_DATE + "2023-09-25 10:15";
+ public static final String MESSAGE_NO_HISTORY_FOUND = "No history found for the person";
private final int personId;
private final LocalDateTime dateTime;
@@ -39,29 +41,20 @@ public ViewHistoryCommand(int personId, LocalDateTime dateTime) {
this.dateTime = dateTime;
}
- /**
- * @param personId of the person to view the history of
- */
- public ViewHistoryCommand(int personId) {
- requireNonNull(personId); // Only patientId is mandatory
- this.personId = personId;
- this.dateTime = null; // Handle the case when dateTime is not provided
- }
-
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- ObservableList allPersons = model.getFilteredPersonList();
+ ObservableList allPersons = model.getAllPersons();
Person personToView = model.getFilteredPersonById(allPersons, personId);
if (personToView == null) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ throw new CommandException(Messages.MESSAGE_INVALID_ID);
}
LocalDateTime historyDateTime;
String history;
if (dateTime != null) {
historyDateTime = dateTime;
- history = personToView.getAppointment(historyDateTime, personId).toString();
+ history = personToView.getOneHistory(historyDateTime, personId);
} else {
history = personToView.getStringAppointments();
}
@@ -88,6 +81,8 @@ public boolean equals(Object other) {
// state check
ViewHistoryCommand e = (ViewHistoryCommand) other;
return personId == (e.personId)
- && dateTime.equals(e.dateTime);
+ && (dateTime == null
+ ? dateTime == e.dateTime
+ : dateTime.equals(e.dateTime));
}
}
diff --git a/src/main/java/seedu/address/logic/parser/AddAppointmentCommandParser.java b/src/main/java/seedu/address/logic/parser/AddAppointmentCommandParser.java
index bacbc481850..9db9e3ac6b2 100644
--- a/src/main/java/seedu/address/logic/parser/AddAppointmentCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddAppointmentCommandParser.java
@@ -49,7 +49,7 @@ public AddAppointmentCommand parse(String args) throws ParseException {
String remarks = argumentMultimap.getValue(PREFIX_REMARK).orElse("");
String appointmentTime = String.valueOf(requireNonNull(argumentMultimap.getValue(PREFIX_DATE)));
- LocalDateTime time = ParserUtil.parseDate(appointmentTime);
+ LocalDateTime time = ParserUtil.parseDateWithNoLimit(appointmentTime);
return new AddAppointmentCommand(time, patientId, doctorId, remarks);
}
diff --git a/src/main/java/seedu/address/logic/parser/AddNotesCommandParser.java b/src/main/java/seedu/address/logic/parser/AddRemarksCommandParser.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/AddNotesCommandParser.java
rename to src/main/java/seedu/address/logic/parser/AddRemarksCommandParser.java
index 26e48ff952c..37bfd340dfc 100644
--- a/src/main/java/seedu/address/logic/parser/AddNotesCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddRemarksCommandParser.java
@@ -1,5 +1,6 @@
package seedu.address.logic.parser;
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_REMARK;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.Messages.MESSAGE_INVALID_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
@@ -8,40 +9,43 @@
import java.util.stream.Stream;
import seedu.address.commons.exceptions.InvalidIdException;
-import seedu.address.logic.commands.AddNotesCommand;
+import seedu.address.logic.commands.AddRemarksCommand;
import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.person.Remark;
/**
* Parses input arguments and adds notes to a Patient.
*/
-public class AddNotesCommandParser implements Parser {
+public class AddRemarksCommandParser implements Parser {
/**
* Parses the given {@code String} of arguments in the context of the CreatePatientCommand
* and returns an CreatePatientCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
- public AddNotesCommand parse(String args) throws ParseException {
+ public AddRemarksCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_ID, PREFIX_REMARK);
if (!arePrefixesPresent(argMultimap, PREFIX_ID, PREFIX_REMARK)
|| !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddNotesCommand.MESSAGE_USAGE));
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddRemarksCommand.MESSAGE_USAGE));
}
-
- int patientId;
-
argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_ID, PREFIX_REMARK);
+ String remarkInput = argMultimap.getAllValues(PREFIX_REMARK).get(0);
+ if (remarkInput.trim().isEmpty()) {
+ throw new ParseException(MESSAGE_EMPTY_REMARK);
+ }
+ int patientId;
try {
patientId = ParserUtil.parsePersonId(argMultimap.getAllValues(PREFIX_ID).get(0));
} catch (InvalidIdException e) {
throw new ParseException(MESSAGE_INVALID_ID, e);
}
- String remark = argMultimap.getValue(PREFIX_REMARK).orElse("");
+ Remark remark = new Remark(argMultimap.getValue(PREFIX_REMARK).orElse(""));
- return new AddNotesCommand(patientId, remark);
+ return new AddRemarksCommand(patientId, remark);
}
/**
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
index 1c63aca7336..c025b10f431 100644
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
@@ -9,14 +9,14 @@
import seedu.address.commons.core.LogsCenter;
import seedu.address.logic.commands.AddAppointmentCommand;
-import seedu.address.logic.commands.AddNotesCommand;
+import seedu.address.logic.commands.AddRemarksCommand;
import seedu.address.logic.commands.CheckAppointmentCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.CreateDoctorCommand;
import seedu.address.logic.commands.CreatePatientCommand;
import seedu.address.logic.commands.DeleteAppointmentCommand;
-import seedu.address.logic.commands.DeletePatientCommand;
+import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
@@ -24,7 +24,6 @@
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.MarkAppointmentCommand;
-import seedu.address.logic.commands.RemarkCommand;
import seedu.address.logic.commands.ViewHistoryCommand;
import seedu.address.logic.parser.exceptions.ParseException;
@@ -71,9 +70,6 @@ public Command parseCommand(String userInput) throws ParseException {
case FindCommand.COMMAND_WORD:
return new FindCommandParser().parse(arguments);
- case RemarkCommand.COMMAND_WORD:
- return new RemarkCommandParser().parse(arguments);
-
case ListCommand.COMMAND_WORD:
return new ListCommand();
@@ -98,11 +94,11 @@ public Command parseCommand(String userInput) throws ParseException {
case CreatePatientCommand.COMMAND_WORD:
return new CreatePatientCommandParser().parse(arguments);
- case DeletePatientCommand.COMMAND_WORD:
- return new DeletePatientCommandParser().parse(arguments);
+ case DeleteCommand.COMMAND_WORD:
+ return new DeleteCommandParser().parse(arguments);
- case AddNotesCommand.COMMAND_WORD:
- return new AddNotesCommandParser().parse(arguments);
+ case AddRemarksCommand.COMMAND_WORD:
+ return new AddRemarksCommandParser().parse(arguments);
case CheckAppointmentCommand.COMMAND_WORD:
return new CheckAppointmentCommandParser().parse(arguments);
diff --git a/src/main/java/seedu/address/logic/parser/CheckAppointmentCommandParser.java b/src/main/java/seedu/address/logic/parser/CheckAppointmentCommandParser.java
index 303767894e6..cec244b2f33 100644
--- a/src/main/java/seedu/address/logic/parser/CheckAppointmentCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/CheckAppointmentCommandParser.java
@@ -30,18 +30,14 @@ public class CheckAppointmentCommandParser implements Parser {
-
+ //@@author Nigeltzy-reused
+ //Reused from @@author sandyk0105's code with minor modifications
/**
* Parses the given {@code String} of arguments in the context of the CreatePatientCommand
* and returns an CreatePatientCommand object for execution.
@@ -49,9 +45,8 @@ public CreateDoctorCommand parse(String args) throws ParseException {
Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
Remark remark = new Remark("");
- Set tagList = new HashSet<>();
- Person doctor = new Person(name, role, phone, email, address, remark, tagList);
+ Person doctor = new Person(name, role, phone, email, address, remark);
return new CreateDoctorCommand(doctor);
@@ -64,4 +59,5 @@ public CreateDoctorCommand parse(String args) throws ParseException {
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
+ //@@author
}
diff --git a/src/main/java/seedu/address/logic/parser/CreatePatientCommandParser.java b/src/main/java/seedu/address/logic/parser/CreatePatientCommandParser.java
index 93d57b898fb..7c861c9a017 100644
--- a/src/main/java/seedu/address/logic/parser/CreatePatientCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/CreatePatientCommandParser.java
@@ -6,8 +6,6 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import java.util.HashSet;
-import java.util.Set;
import java.util.stream.Stream;
import seedu.address.logic.commands.CreatePatientCommand;
@@ -18,7 +16,6 @@
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.person.Remark;
-import seedu.address.model.tag.Tag;
/**
@@ -47,9 +44,8 @@ public CreatePatientCommand parse(String args) throws ParseException {
Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
Remark remark = new Remark("");
- Set tagList = new HashSet<>();
- Person patient = new Person(name, role, phone, email, address, remark, tagList);
+ Person patient = new Person(name, role, phone, email, address, remark);
return new CreatePatientCommand(patient);
diff --git a/src/main/java/seedu/address/logic/parser/DeletePatientCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
similarity index 70%
rename from src/main/java/seedu/address/logic/parser/DeletePatientCommandParser.java
rename to src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
index e9cc26f6e90..299bd5b6c4e 100644
--- a/src/main/java/seedu/address/logic/parser/DeletePatientCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
@@ -2,27 +2,26 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.Messages.MESSAGE_INVALID_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import java.util.stream.Stream;
import seedu.address.commons.exceptions.InvalidIdException;
-import seedu.address.logic.commands.DeletePatientCommand;
+import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.parser.exceptions.ParseException;
/**
- * Parses input arguments and creates a new DeletePatientCommand object
+ * Parses input arguments and creates a new DeleteCommand object
*/
-public class DeletePatientCommandParser implements Parser {
+public class DeleteCommandParser implements Parser {
/**
- * Parses the given {@code String} of arguments in the context of the DeletePatientCommand
- * and returns a DeletePatientCommand object for execution.
+ * Parses the given {@code String} of arguments in the context of the DeleteCommand
+ * and returns a DeleteCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
@Override
- public DeletePatientCommand parse(String args) throws ParseException {
+ public DeleteCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argumentMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ID);
@@ -30,15 +29,15 @@ public DeletePatientCommand parse(String args) throws ParseException {
if (!arePrefixesPresent(argumentMultimap, PREFIX_ID)
|| !argumentMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- DeletePatientCommand.MESSAGE_USAGE));
+ DeleteCommand.MESSAGE_USAGE));
}
int patientId;
try {
patientId = ParserUtil.parsePersonId(argumentMultimap.getAllValues(PREFIX_ID).get(0));
} catch (InvalidIdException e) {
- throw new ParseException(MESSAGE_INVALID_ID, e);
+ throw new ParseException(e.getMessage());
}
- return new DeletePatientCommand(patientId);
+ return new DeleteCommand(patientId);
}
/**
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
index 46b3309a78b..260dfdcf86f 100644
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
@@ -4,20 +4,14 @@
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
+import seedu.address.commons.exceptions.InvalidIdException;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.tag.Tag;
/**
* Parses input arguments and creates a new EditCommand object
@@ -32,23 +26,26 @@ public class EditCommandParser implements Parser {
public EditCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- Index index;
+ ArgumentTokenizer.tokenize(args, PREFIX_ID, PREFIX_NAME, PREFIX_PHONE,
+ PREFIX_EMAIL, PREFIX_ADDRESS);
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
- }
-
- argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS);
+ argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_ID, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS);
EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
-
+ int idToEdit;
if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
}
+ try {
+ if (argMultimap.getValue(PREFIX_ID).isPresent()) {
+ idToEdit = ParserUtil.parsePersonId(argMultimap.getValue(PREFIX_ID).get());
+ } else {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE));
+ }
+ } catch (InvalidIdException e) {
+ throw new ParseException(e.getMessage());
+ }
+
if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
}
@@ -58,28 +55,13 @@ public EditCommand parse(String args) throws ParseException {
if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
}
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
if (!editPersonDescriptor.isAnyFieldEdited()) {
throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
}
- return new EditCommand(index, editPersonDescriptor);
+ return new EditCommand(idToEdit, editPersonDescriptor);
}
- /**
- * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
- * If {@code tags} contain only one element which is an empty string, it will be parsed into a
- * {@code Set} containing zero tags.
- */
- private Optional> parseTagsForEdit(Collection tags) throws ParseException {
- assert tags != null;
-
- if (tags.isEmpty()) {
- return Optional.empty();
- }
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
}
diff --git a/src/main/java/seedu/address/logic/parser/MarkAppointmentCommandParser.java b/src/main/java/seedu/address/logic/parser/MarkAppointmentCommandParser.java
index 8629f2b3e16..1533161b47c 100644
--- a/src/main/java/seedu/address/logic/parser/MarkAppointmentCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/MarkAppointmentCommandParser.java
@@ -45,7 +45,7 @@ public MarkAppointmentCommand parse(String args) throws ParseException {
throw new ParseException(MESSAGE_INVALID_ID, e);
}
String appointmentTime = String.valueOf(requireNonNull(argumentMultimap.getValue(PREFIX_DATE)));
- LocalDateTime time = ParserUtil.parseDate(appointmentTime);
+ LocalDateTime time = ParserUtil.parseDateWithNoLimit(appointmentTime);
return new MarkAppointmentCommand(time, patientId, doctorId);
}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
index 36280d22f3d..7ca615445cd 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -6,49 +6,31 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import seedu.address.commons.core.index.Index;
import seedu.address.commons.exceptions.InvalidIdException;
-import seedu.address.commons.util.StringUtil;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
+import seedu.address.model.person.Id;
import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
/**
* Contains utility methods used for parsing strings in the various *Parser classes.
*/
public class ParserUtil {
- public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
- public static final String MESSAGE_INVALID_PATIENT_ID = "The patient id you have keyed in is invalid";
- public static final String MESSAGE_INVALID_DOCTOR_ID = "The doctor id you have keyed in is invalid";
-
- /**
- * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
- * trimmed.
- * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
- */
- public static Index parseIndex(String oneBasedIndex) throws ParseException {
- String trimmedIndex = oneBasedIndex.trim();
- if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
- }
- return Index.fromOneBased(Integer.parseInt(trimmedIndex));
- }
-
/**
* Parses {@code id} into an {@code Id} and returns it. Leading and trailing whitespaces will be
* trimmed.
* @throws InvalidIdException if the specified person id is invalid.
*/
public static int parsePersonId(String id) throws InvalidIdException {
+ requireNonNull(id);
String trimmedId = id.trim();
+ if (!Id.isValidId(trimmedId)) {
+ throw new InvalidIdException(Id.MESSAGE_CONSTRAINTS);
+ }
return Integer.parseInt(trimmedId);
}
@@ -91,6 +73,23 @@ public static LocalDateTime parseDate(String date) throws ParseException {
return time;
}
+ /**
+ * Parses a {@code String date} into a {@code LocalDateTime}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code date} is invalid or not in the expected format.
+ */
+ public static LocalDateTime parseDateWithNoLimit(String date) throws ParseException {
+ requireNonNull(date);
+ String trimmedDate = date.trim().replace("Optional[", "").replace("]", "");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+ try {
+ return LocalDateTime.parse(trimmedDate, formatter);
+ } catch (DateTimeParseException e) {
+ throw new ParseException("Invalid date-time format, please use yyyy-MM-dd HH:mm.");
+ }
+ }
+
/**
* Parses a {@code String date} into a {@code LocalDate}.
* Leading and trailing whitespaces will be trimmed.
@@ -99,20 +98,13 @@ public static LocalDateTime parseDate(String date) throws ParseException {
*/
public static LocalDate parseDayDate(String date) throws ParseException {
requireNonNull(date);
- String trimmedDate = date.trim();
- LocalDate parsedDate;
- LocalDate currentDate = LocalDate.now();
+ String trimmedDate = date.trim().replace("Optional[", "").replace("]", "");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
- parsedDate = LocalDate.parse(trimmedDate, formatter);
+ return LocalDate.parse(trimmedDate, formatter);
} catch (DateTimeParseException e) {
- throw new ParseException("Invalid date format, please use yyyy-MM-dd.");
+ throw new ParseException("Invalid date-time format, please use yyyy-MM-dd");
}
-
- if (currentDate.isAfter(parsedDate)) {
- throw new ParseException("Invalid date entered. The date can't be in the past!");
- }
- return parsedDate;
}
@@ -161,30 +153,4 @@ public static Email parseEmail(String email) throws ParseException {
return new Email(trimmedEmail);
}
- /**
- * Parses a {@code String tag} into a {@code Tag}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code tag} is invalid.
- */
- public static Tag parseTag(String tag) throws ParseException {
- requireNonNull(tag);
- String trimmedTag = tag.trim();
- if (!Tag.isValidTagName(trimmedTag)) {
- throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(trimmedTag);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set}.
- */
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
- }
- return tagSet;
- }
}
diff --git a/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java b/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java
deleted file mode 100644
index 613f9debf69..00000000000
--- a/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.logic.commands.RemarkCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Remark;
-
-/**
- * Parses input arguments and creates a new RemarkCommand object.
- */
-public class RemarkCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the RemarkCommand
- * and returns a RemarkCommand object for execution.
- *
- * @param args the input arguments string.
- * @return a RemarkCommand object.
- * @throws ParseException if the user input does not conform to the expected format.
- */
- @Override
- public RemarkCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_REMARK);
-
- Index index;
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (IllegalValueException ive) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- RemarkCommand.MESSAGE_USAGE), ive);
- }
-
- String remark = argMultimap.getValue(PREFIX_REMARK).orElse("");
-
- return new RemarkCommand(index, new Remark(remark));
- }
-}
diff --git a/src/main/java/seedu/address/logic/parser/ViewHistoryCommandParser.java b/src/main/java/seedu/address/logic/parser/ViewHistoryCommandParser.java
index dd285f42f3c..035a0c410f6 100644
--- a/src/main/java/seedu/address/logic/parser/ViewHistoryCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/ViewHistoryCommandParser.java
@@ -31,11 +31,8 @@ public class ViewHistoryCommandParser implements Parser {
@Override
public ViewHistoryCommand parse(String args) throws ParseException {
requireNonNull(args);
-
- // Tokenize the arguments and look for the /d (date) and /id (patient ID) prefixes
ArgumentMultimap argumentMultimap = ArgumentTokenizer.tokenize(args, PREFIX_DATE, PREFIX_ID);
- // Check if /z prefixes is present, and there is no unexpected preamble
if (!arePrefixesPresent(argumentMultimap, PREFIX_ID)
|| !argumentMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
@@ -50,18 +47,17 @@ public ViewHistoryCommand parse(String args) throws ParseException {
throw new ParseException(MESSAGE_INVALID_ID, e);
}
- // Parse the date from the /d prefix, or set it to null if not provided
+ // Parse the date from the x/ prefix, or set it to null if not provided
LocalDateTime dateTime = null;
Optional dateTimeString = argumentMultimap.getValue(PREFIX_DATE);
if (dateTimeString.isPresent()) {
try {
- dateTime = ParserUtil.parseDate(dateTimeString.get().trim());
+ dateTime = ParserUtil.parseDateWithNoLimit(dateTimeString.get().trim());
} catch (ParseException e) {
- throw new ParseException("Invalid date-time format. Please use yyyy-MM-dd HH:mm.");
+ throw new ParseException("Invalid date-time format, please use yyyy-MM-dd HH:mm.");
}
}
- // Return the constructed ViewHistoryCommand with patientId and the parsed or null dateTime
return new ViewHistoryCommand(patientId, dateTime);
}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
index 73397161e84..297168c011e 100644
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ b/src/main/java/seedu/address/model/AddressBook.java
@@ -67,6 +67,14 @@ public boolean hasPerson(Person person) {
return persons.contains(person);
}
+ /**
+ * Returns the role of a person (patient or doctor)
+ */
+ public String getPersonRole(Person person) {
+ requireNonNull(person);
+ return persons.getPersonRole(person);
+ }
+
/**
* Adds a person to the address book.
* The person must not already exist in the address book.
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
index ded57d840e2..9c22c682caf 100644
--- a/src/main/java/seedu/address/model/Model.java
+++ b/src/main/java/seedu/address/model/Model.java
@@ -57,12 +57,18 @@ public interface Model {
*/
boolean hasPerson(Person person);
+ /**
+ * Returns the role of a person (patient or doctor)
+ */
+ String getPersonRole(Person person);
+
/**
* Deletes the given person.
* The person must exist in the address book.
*/
void deletePerson(Person target);
+
/**
* Adds the given person.
* {@code person} must not already exist in the address book.
@@ -79,6 +85,8 @@ public interface Model {
/** Returns an unmodifiable view of the filtered person list */
ObservableList getFilteredPersonList();
+ ObservableList getAllPersons();
+
/** Returns an unmodifiable view of the filtered person list by Id search*/
ObservableList getFilteredPersonById(int id);
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index 41a1c28afee..5cc2431fdc2 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -22,6 +22,7 @@ public class ModelManager implements Model {
private final AddressBook addressBook;
private final UserPrefs userPrefs;
private final FilteredList filteredPersons;
+ private final ObservableList allPersons;
/**
* Initializes a ModelManager with the given addressBook and userPrefs.
@@ -33,13 +34,14 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs
this.addressBook = new AddressBook(addressBook);
this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
+ this.allPersons = this.addressBook.getPersonList(); // Unfiltered list of all persons
+ this.filteredPersons = new FilteredList<>(allPersons); // Filtered view based on allPersons
/*
for (Person person : filteredPersons) {
- if (person.getRole().equals("doctor")) {
+ if (person.getRole().equals("PATIENT")) {
Doctor.addDoctors((Doctor) person);
}
- if (person.getRole().equals("patient")) {
+ if (person.getRole().equals("PATIENT")) {
Patient.addPatient(person);
}
}
@@ -103,6 +105,12 @@ public boolean hasPerson(Person person) {
return addressBook.hasPerson(person);
}
+ @Override
+ public String getPersonRole(Person person) {
+ requireNonNull(person);
+ return addressBook.getPersonRole(person);
+ }
+
@Override
public void deletePerson(Person target) {
addressBook.removePerson(target);
@@ -154,7 +162,6 @@ public Person getFilteredPatientById(ObservableList allPersons, int id)
Person patient = null;
for (Person person : allPersons) {
if (person.getId() == id) {
- System.out.println(person.getName());
patient = person;
break;
}
@@ -174,6 +181,10 @@ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
return doctor;
}
+ public ObservableList getAllPersons() {
+ return allPersons;
+ }
+
@Override
public void updateFilteredPersonList(Predicate predicate) {
requireNonNull(predicate);
diff --git a/src/main/java/seedu/address/model/person/Appointment.java b/src/main/java/seedu/address/model/person/Appointment.java
index ab8df87d674..0f130fa1f9e 100644
--- a/src/main/java/seedu/address/model/person/Appointment.java
+++ b/src/main/java/seedu/address/model/person/Appointment.java
@@ -3,6 +3,7 @@
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
@@ -13,7 +14,7 @@ public class Appointment {
private final int patientId;
private final int doctorId;
private final String remarks;
- private final boolean completed;
+ private boolean completed;
/**
* Creates an appointment instance associated with the specified patient, doctor, and remarks.
@@ -56,8 +57,12 @@ public String getRemarks() {
return remarks;
}
- public Appointment markAsComplete() {
- return new Appointment(this.dateTime, this.patientId, this.doctorId, this.remarks, true);
+ public Boolean isCompleted() {
+ return completed;
+ }
+
+ public void markAsComplete() {
+ this.completed = true;
}
/**
* Determines if an appointment is the same appointment including checking for remarks.
@@ -65,7 +70,7 @@ public Appointment markAsComplete() {
* @param o Object to be compared to.
* @return True if all details are the same (including checking remarks), false if otherwise.
*/
- public boolean equalsIncludngRemarks(Object o) {
+ public boolean equalsIncludingRemarks(Object o) {
if (this == o) {
return true;
}
@@ -81,6 +86,7 @@ public boolean equalsIncludngRemarks(Object o) {
&& Objects.equals(remarks, appointment.remarks);
}
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -104,16 +110,16 @@ public int hashCode() {
@Override
public String toString() {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
if (this.completed) {
- return "Appointment: " + getDateTime() + " for " + getPatientId()
+ return "[Completed] Appointment: " + getDateTime().format(formatter) + " for " + getPatientId()
+ " (patient id) with " + getDoctorId() + " (doctor id). "
+ "Remarks: " + getRemarks();
} else {
- return "Appointment: " + getDateTime() + " for " + getPatientId()
+ return "[Incomplete] Appointment: " + getDateTime().format(formatter) + " for " + getPatientId()
+ " (patient id) with " + getDoctorId() + " (doctor id). "
+ "Remarks: " + getRemarks();
}
}
}
-
diff --git a/src/main/java/seedu/address/model/person/Appointmentable.java b/src/main/java/seedu/address/model/person/Appointmentable.java
index 5c1793055d2..271fbb5d46a 100644
--- a/src/main/java/seedu/address/model/person/Appointmentable.java
+++ b/src/main/java/seedu/address/model/person/Appointmentable.java
@@ -59,5 +59,6 @@ public abstract Appointment getAppointment(LocalDateTime dateTime, int patientId
* @param patientId Id of patient in the appointment.
* @param doctorId Id of doctor in the appointment.
*/
- public abstract boolean markAppointment(LocalDateTime dateTime, int patientId, int doctorId);
+ public abstract void markAppointment(LocalDateTime dateTime, int patientId, int doctorId)
+ throws CommandException;
}
diff --git a/src/main/java/seedu/address/model/person/Id.java b/src/main/java/seedu/address/model/person/Id.java
index 047eaf66f1b..428e54122ee 100644
--- a/src/main/java/seedu/address/model/person/Id.java
+++ b/src/main/java/seedu/address/model/person/Id.java
@@ -8,6 +8,9 @@
* Id class that auto-increments and generates an automated unique Id number for Doctors and Patients separately.
*/
public class Id {
+ public static final String MESSAGE_CONSTRAINTS =
+ "ID is in an invalid format. Refer to the User Guide in the help command for more information.";
+ public static final String VALIDATION_REGEX = "\\d+";
public static final String DOCTOR = "DOCTOR";
private static final String PATIENT = "PATIENT";
private static int patientIdCounter = 0;
@@ -68,6 +71,57 @@ public static void initializeCounters(List doctorIds, List pat
.max()
.orElse(0) + 2; // Increment by 2 to continue from the last used patient ID
}
+ public static boolean isValidId(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Resets the patientIdCounter
+ */
+ public static void resetPatientIdCounter() {
+ patientIdCounter = 0;
+ }
+
+ /**
+ * Resets the doctorIdCounter
+ */
+ public static void resetDoctorIdCounter() {
+ doctorIdCounter = 1;
+ }
+
+ /**
+ * Gets the current patientIdCounter
+ */
+ public static int getCurrentPatientIdCounter() {
+ return patientIdCounter;
+ }
+
+ /**
+ * Gets the current doctorIdCounter
+ */
+ public static int getCurrentDoctorIdCounter() {
+ return doctorIdCounter;
+ }
+
+ /**
+ * Reduces the current patientIdCounter by 2
+ */
+ public static void reduceCurrentPatientIdCounter() {
+ if (patientIdCounter == 0) {
+ } else {
+ patientIdCounter = patientIdCounter - 2;
+ }
+ }
+
+ /**
+ * Reduces the current doctorIdCounter by 2
+ */
+ public static void reduceCurrentDoctorIdCounter() {
+ if (doctorIdCounter == 0) {
+ } else {
+ doctorIdCounter = doctorIdCounter - 2;
+ }
+ }
@Override
public String toString() {
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
index b4a8216dbe5..36cd5980214 100644
--- a/src/main/java/seedu/address/model/person/Person.java
+++ b/src/main/java/seedu/address/model/person/Person.java
@@ -1,20 +1,20 @@
package seedu.address.model.person;
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllPositive;
+import static seedu.address.logic.Messages.MESSAGE_COMPLETED_APPOINTMENT;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.stream.Collectors;
+import javafx.collections.ObservableList;
import seedu.address.commons.core.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.tag.Tag;
+import seedu.address.model.Model;
/**
* Represents a Person in the address book.
@@ -28,33 +28,49 @@ public class Person implements Appointmentable {
private final Email email;
private final int id;
private final Address address;
- private final Remark remark;
- private final Set tags = new HashSet<>();
+ private Remark remark;
private List appointments;
/**
* Every field must be present and not null.
*/
public Person(Name name, String role, Phone phone, Email email,
- Address address, Remark remark, Set tags) {
- requireAllNonNull(name, role, phone, email, address, tags);
+ Address address, Remark remark) {
+ requireAllNonNull(name, role, phone, email, address);
this.name = name;
this.role = role;
this.phone = phone;
this.email = email;
this.address = address;
this.remark = remark;
- this.tags.addAll(tags);
this.id = new Id(role).getIdValue();
this.appointments = new ArrayList<>();
}
/**
- * Creates a Person with the given fields. Each field must be present and not null.
+ * Creates a patient with a fixed ID
*/
public Person(Name name, int id, String role, Phone phone, Email email,
- Address address, Remark remark, List appointments, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
+ Address address, Remark remark) {
+ requireAllNonNull(name, role, phone, email, address);
+ requireAllPositive(id);
+ this.name = name;
+ this.role = role;
+ this.phone = phone;
+ this.email = email;
+ this.address = address;
+ this.remark = remark;
+ this.id = id;
+ this.appointments = new ArrayList<>();
+ }
+
+ /**
+ * Creates a Person with the given fields. Each field must be present and not null.
+ */
+ public Person(Name name, int id, String role, Phone phone, Email email,
+ Address address, Remark remark, List appointments) {
+ requireAllNonNull(name, phone, email, address);
+ requireAllPositive(id);
this.name = name;
this.id = id;
this.role = role;
@@ -62,7 +78,6 @@ public Person(Name name, int id, String role, Phone phone, Email email,
this.email = email;
this.address = address;
this.remark = remark;
- this.tags.addAll(tags);
this.appointments = appointments;
}
@@ -90,48 +105,26 @@ public Remark getRemark() {
return remark;
}
- public void addNotes(String notes) {
- this.remark.addNotes(notes);
+ public List getAllAppointments() {
+ return this.appointments;
+ }
+
+ /**
+ * Adds additional remarks to a person
+ */
+ public Remark addRemarks(String remarks) {
+ remark.addRemarks(remarks);
+ return remark;
}
public int getId() {
return id;
}
+
public List getAppointments() {
return appointments;
}
-
- // // Method in the class (e.g., Patient or Doctor) to retrieve the appointment details
- // public String getOneHistory(LocalDateTime dateTime, Id patientId) {
- // try {
- // Appointment appointment = history.getOneAppointmentDetail(dateTime, patientId);
- // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
- // String time = "DateTime: " + dateTime.format(formatter);
- // return time + " " + appointment.toString();
- // } catch (AppNotFoundException e) {
- // return "No appointment found for the given date, patient, and doctor.";
- // }
- // }
- //
- // public String getOneDayDoctorAppointment(LocalDate date, Id doctorId) {
- // try {
- // String appointments = history.getDoctorAppointmentsForDay(date, doctorId);
- // return appointments; // Assuming the Appointment class has a toString() method for formatting
- // } catch (AppNotFoundException e) {
- // return "No appointment found for the given date and doctor.";
- // }
- // }
-
-
- /**
- * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- */
- public Set getTags() {
- return Collections.unmodifiableSet(tags);
- }
-
/**
* Returns true if both persons of the same name have at least one other identity field that is the same.
* This defines a weaker notion of equality between two persons.
@@ -142,10 +135,17 @@ public boolean isSamePerson(Person otherPerson) {
}
return otherPerson != null
- && otherPerson.getName().equals(getName())
+ && normalizeName(otherPerson.getName()).equals(normalizeName(getName()))
&& (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail()));
}
+ /**
+ * Normalizes a name by converting it to lowercase and removing all spaces.
+ */
+ private String normalizeName(Name name) {
+ return name.toString().toLowerCase().replaceAll("\\s+", "");
+ }
+
/**
* Adds a new appointment at the specified time, for the respective patient and doctor.
*
@@ -157,7 +157,13 @@ public boolean isSamePerson(Person otherPerson) {
@Override
public boolean addAppointment(LocalDateTime dateTime, int patientId, int doctorId, String remarks) {
requireAllNonNull(dateTime, patientId, doctorId, remarks);
+ // Check for duplicates before adding
+ boolean appointmentExists = appointments.stream()
+ .anyMatch(appointment -> appointment.equals(new Appointment(dateTime, patientId, doctorId, remarks)));
+ if (appointmentExists) {
+ return false; // Appointment already exists, do not add
+ }
return appointments.add(new Appointment(dateTime, patientId, doctorId, remarks));
}
@@ -174,6 +180,30 @@ public boolean deleteAppointment(LocalDateTime dateTime, int patientId, int doct
requireAllNonNull(dateTime, patientId, doctorId);
return appointments.remove(new Appointment(dateTime, patientId, doctorId, ""));
}
+ /**
+ * Deletes all appointments for this person based on their role.
+ * If the role is "patient", deletes appointments where this person is the patient.
+ * If the role is "doctor", deletes appointments where this person is the doctor.
+ */
+ public void deleteAllAppointments(Model model) {
+ if (role.equals("patient")) {
+ for (Appointment appointment : appointments) {
+ if (appointment.getDoctorId() == this.id) {
+ ObservableList allPersons = model.getFilteredPersonList();
+ Person doctor = model.getFilteredPersonById(allPersons, appointment.getDoctorId());
+ doctor.deleteAppointment(appointment.getDateTime(), appointment.getPatientId(), this.id);
+ }
+ }
+ } else {
+ for (Appointment appointment : appointments) {
+ if (appointment.getDoctorId() == this.id) {
+ ObservableList allPersons = model.getFilteredPersonList();
+ Person patient = model.getFilteredPersonById(allPersons, appointment.getPatientId());
+ patient.deleteAppointment(appointment.getDateTime(), appointment.getPatientId(), this.id);
+ }
+ }
+ }
+ }
/**
* Gets an appointment at the specified time, with the respective patient and doctor.
@@ -197,23 +227,27 @@ public Appointment getAppointment(LocalDateTime dateTime, int patientId, int doc
}
- public Appointment getAppointment(LocalDateTime dateTime, int patientId) throws CommandException {
- requireAllNonNull(dateTime, patientId);
+ public String getOneHistory(LocalDateTime dateTime, int personId) {
+ requireAllNonNull(dateTime, personId);
List apts = appointments.stream()
- .filter(apt -> apt.getDateTime().toString().equals(dateTime.toString()))
- .filter(apt -> apt.getPatientId() == patientId)
+ .filter(apt -> apt.getDateTime().equals(dateTime))
+ .filter(apt -> (this.role.equals("PATIENT") && apt.getPatientId() == personId)
+ || (this.role.equals("DOCTOR") && apt.getDoctorId() == personId))
.collect(Collectors.toList());
- if (apts.isEmpty() || apts.size() == 0) {
- throw new CommandException(Messages.MESSAGE_NO_APPOINTMENTS_FOUND);
+ if (apts.isEmpty()) {
+ return null;
}
-
- return apts.get(0);
+ return apts.get(0).toString();
}
public String getStringAppointments() {
final StringBuilder builder = new StringBuilder();
appointments.stream()
- .forEach(builder::append);
+ .forEach(appointment ->
+ builder.append(appointment).append("\n")); // Add newline after each appointment
+ if (builder.isEmpty()) {
+ return null;
+ }
return builder.toString();
}
@@ -227,7 +261,7 @@ public String getStringAppointmentsForDay(LocalDate date) {
// Check if there are no appointments for the day
if (appointmentsForDay.isEmpty()) {
- return String.format("No appointments found for the day: %s", date.toString());
+ return null;
}
// Build a string for the appointments on the given day
@@ -241,6 +275,9 @@ public String getStringAppointmentsForDay(LocalDate date) {
}
+ public void editRemark(Remark remark) {
+ this.remark = remark;
+ }
@Override
public boolean editAppointment(LocalDateTime dateTime, int patientId, int doctorId) {
@@ -266,25 +303,25 @@ public boolean equals(Object other) {
return otherPerson.getName().equals(getName())
&& otherPerson.getPhone().equals(getPhone())
&& otherPerson.getEmail().equals(getEmail())
- && otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
+ && otherPerson.getAddress().equals(getAddress());
}
@Override
public int hashCode() {
// use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
+ return Objects.hash(name, phone, email, address);
}
@Override
- public boolean markAppointment(LocalDateTime dateTime, int patientId, int doctorId) {
+ public void markAppointment(LocalDateTime dateTime, int patientId, int doctorId)
+ throws CommandException {
requireAllNonNull(dateTime, patientId, doctorId);
- try {
- getAppointment(dateTime, patientId, doctorId).markAsComplete();
- } catch (CommandException e) {
- return false;
+ Appointment appointment;
+ appointment = getAppointment(dateTime, patientId, doctorId);
+ if (appointment.isCompleted()) {
+ throw new CommandException(MESSAGE_COMPLETED_APPOINTMENT);
}
- return true;
+ appointment.markAsComplete();
}
@Override
@@ -307,9 +344,9 @@ public String toString() {
if (getAppointments() != null) {
getAppointments().forEach(builder::append);
}
- builder.append(getAppointments())
- .append(" Tags: ");
- getTags().forEach(builder::append);
return builder.toString();
}
+
}
+
+
diff --git a/src/main/java/seedu/address/model/person/Remark.java b/src/main/java/seedu/address/model/person/Remark.java
index 664645260bf..cc280f5e150 100644
--- a/src/main/java/seedu/address/model/person/Remark.java
+++ b/src/main/java/seedu/address/model/person/Remark.java
@@ -25,7 +25,7 @@ public Remark(String remark) {
* Adds notes to this Remark
* @param notes notes to be added
*/
- public void addNotes(String notes) {
+ public void addRemarks(String notes) {
requireNonNull(notes);
this.value += "\n" + notes;
}
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java
index cc0a68d79f9..cce15918068 100644
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ b/src/main/java/seedu/address/model/person/UniquePersonList.java
@@ -36,6 +36,15 @@ public boolean contains(Person toCheck) {
return internalList.stream().anyMatch(toCheck::isSamePerson);
}
+ /**
+ * Returns the role of a person (patient or doctor or null if undefined)
+ */
+ public String getPersonRole(Person person) {
+ requireNonNull(person);
+ return internalList.stream().filter(person::isSamePerson)
+ .map(Person::getRole).findFirst().orElse(null);
+ }
+
/**
* Adds a person to the list.
* The person must not already exist in the list.
diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java
deleted file mode 100644
index f1a0d4e233b..00000000000
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package seedu.address.model.tag;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Tag in the address book.
- * Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)}
- */
-public class Tag {
-
- public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric";
- public static final String VALIDATION_REGEX = "\\p{Alnum}+";
-
- public final String tagName;
-
- /**
- * Constructs a {@code Tag}.
- *
- * @param tagName A valid tag name.
- */
- public Tag(String tagName) {
- requireNonNull(tagName);
- checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS);
- this.tagName = tagName;
- }
-
- /**
- * Returns true if a given string is a valid tag name.
- */
- public static boolean isValidTagName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Tag)) {
- return false;
- }
-
- Tag otherTag = (Tag) other;
- return tagName.equals(otherTag.tagName);
- }
-
- @Override
- public int hashCode() {
- return tagName.hashCode();
- }
-
- /**
- * Format state as text for viewing.
- */
- public String toString() {
- return '[' + tagName + ']';
- }
-
-}
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
index 78d007da5da..0fe77b9b05c 100644
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java
@@ -1,9 +1,5 @@
package seedu.address.model.util;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.person.Address;
@@ -12,7 +8,6 @@
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.person.Remark;
-import seedu.address.model.tag.Tag;
/**
* Contains utility methods for populating {@code AddressBook} with sample data.
@@ -22,62 +17,56 @@ public class SampleDataUtil {
public static final Remark EMPTY_REMARK = new Remark("");
private static Person person1 = new Person(
new Name("Alex Yeoh"),
- "patient",
+ "PATIENT",
new Phone("87438807"),
new Email("alexyeoh@example.com"),
new Address("Blk 30 Geylang Street 29, #06-40"),
- EMPTY_REMARK,
- getTagSet("friends")
+ EMPTY_REMARK
);
private static Person person2 = new Person(
new Name("Bernice Yu"),
- "patient",
+ "PATIENT",
new Phone("99272758"),
new Email("berniceyu@example.com"),
new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- EMPTY_REMARK,
- getTagSet("colleagues", "friends")
+ EMPTY_REMARK
);
private static Person person3 = new Person(
new Name("Charlotte Oliveiro"),
- "patient",
+ "PATIENT",
new Phone("93210283"),
new Email("charlotte@example.com"),
new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- EMPTY_REMARK,
- getTagSet("neighbours")
+ EMPTY_REMARK
);
private static Person person4 = new Person(
new Name("David Li"),
- "patient",
+ "PATIENT",
new Phone("91031282"),
new Email("lidavid@example.com"),
new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- EMPTY_REMARK,
- getTagSet("family")
+ EMPTY_REMARK
);
private static Person person5 = new Person(
new Name("Irfan Ibrahim"),
- "patient",
+ "PATIENT",
new Phone("92492021"),
new Email("irfan@example.com"),
new Address("Blk 47 Tampines Street 20, #17-35"),
- EMPTY_REMARK,
- getTagSet("classmates")
+ EMPTY_REMARK
);
private static Person person6 = new Person(
new Name("Roy Balakrishnan"),
- "patient",
+ "PATIENT",
new Phone("92624417"),
new Email("royb@example.com"),
new Address("Blk 45 Aljunied Street 85, #11-31"),
- EMPTY_REMARK,
- getTagSet("colleagues")
+ EMPTY_REMARK
);
@@ -95,13 +84,4 @@ public static ReadOnlyAddressBook getSampleAddressBook() {
return sampleAb;
}
- /**
- * Returns a tag set containing the list of strings given.
- */
- public static Set getTagSet(String... strings) {
- return Arrays.stream(strings)
- .map(Tag::new)
- .collect(Collectors.toSet());
- }
-
}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
index f9ce6936ed3..e8f7da20f00 100644
--- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
+++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
@@ -1,9 +1,7 @@
package seedu.address.storage;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -18,7 +16,6 @@
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.person.Remark;
-import seedu.address.model.tag.Tag;
/**
* Jackson-friendly version of {@link Person}.
@@ -34,7 +31,6 @@ class JsonAdaptedPerson {
private final String email;
private final String address;
private final String remark;
- private final List tags = new ArrayList<>();
private final List appointments = new ArrayList<>();
/**
@@ -48,8 +44,7 @@ public JsonAdaptedPerson(@JsonProperty("name") String name,
@JsonProperty("email") String email,
@JsonProperty("address") String address,
@JsonProperty("remark") String remark,
- @JsonProperty("appointments") List appointments,
- @JsonProperty("tags") List tags) {
+ @JsonProperty("appointments") List appointments) {
this.name = name;
this.id = id;
this.role = role;
@@ -60,9 +55,6 @@ public JsonAdaptedPerson(@JsonProperty("name") String name,
if (appointments != null) {
this.appointments.addAll(appointments);
}
- if (tags != null) {
- this.tags.addAll(tags);
- }
}
/**
@@ -79,9 +71,6 @@ public JsonAdaptedPerson(Person source) {
appointments.addAll(source.getAppointments().stream()
.map(JsonAdaptedAppointment::new)
.collect(Collectors.toList()));
- tags.addAll(source.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList()));
}
/**
@@ -90,10 +79,6 @@ public JsonAdaptedPerson(Person source) {
* @throws IllegalValueException if there were any data constraints violated in the adapted person.
*/
public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (JsonAdaptedTag tag : tags) {
- personTags.add(tag.toModelType());
- }
final List personAppointments = new ArrayList<>();
for (JsonAdaptedAppointment appointment : appointments) {
personAppointments.add(appointment.toModelType());
@@ -151,8 +136,6 @@ public Person toModelType() throws IllegalValueException {
final List modelAppointments = new ArrayList<>(personAppointments);
- final Set modelTags = new HashSet<>(personTags);
-
return new Person(modelName,
modelId,
modelRole,
@@ -160,8 +143,8 @@ public Person toModelType() throws IllegalValueException {
modelEmail,
modelAddress,
modelRemark,
- modelAppointments,
- modelTags);
+ modelAppointments
+ );
}
public String getId() {
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/address/storage/JsonAdaptedTag.java
deleted file mode 100644
index 0df22bdb754..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package seedu.address.storage;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Tag}.
- */
-class JsonAdaptedTag {
-
- private final String tagName;
-
- /**
- * Constructs a {@code JsonAdaptedTag} with the given {@code tagName}.
- */
- @JsonCreator
- public JsonAdaptedTag(String tagName) {
- this.tagName = tagName;
- }
-
- /**
- * Converts a given {@code Tag} into this class for Jackson use.
- */
- public JsonAdaptedTag(Tag source) {
- tagName = source.tagName;
- }
-
- @JsonValue
- public String getTagName() {
- return tagName;
- }
-
- /**
- * Converts this Jackson-friendly adapted tag object into the model's {@code Tag} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted tag.
- */
- public Tag toModelType() throws IllegalValueException {
- if (!Tag.isValidTagName(tagName)) {
- throw new IllegalValueException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(tagName);
- }
-
-}
diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/address/ui/CommandBox.java
index 9e75478664b..13535d1027a 100644
--- a/src/main/java/seedu/address/ui/CommandBox.java
+++ b/src/main/java/seedu/address/ui/CommandBox.java
@@ -35,7 +35,7 @@ public CommandBox(CommandExecutor commandExecutor) {
* Handles the Enter button pressed event.
*/
@FXML
- private void handleCommandEntered() {
+ void handleCommandEntered() {
String commandText = commandTextField.getText();
if (commandText.equals("")) {
return;
diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/address/ui/HelpWindow.java
index 3f16b2fcf26..4b173f13624 100644
--- a/src/main/java/seedu/address/ui/HelpWindow.java
+++ b/src/main/java/seedu/address/ui/HelpWindow.java
@@ -15,7 +15,7 @@
*/
public class HelpWindow extends UiPart {
- public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html";
+ public static final String USERGUIDE_URL = "https://ay2425s1-cs2103t-t08-3.github.io/tp/UserGuide.html";
public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL;
private static final Logger logger = LogsCenter.getLogger(HelpWindow.class);
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
index bda56bddc60..e4d3a600809 100644
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ b/src/main/java/seedu/address/ui/PersonCard.java
@@ -1,10 +1,7 @@
package seedu.address.ui;
-import java.util.Comparator;
-
import javafx.fxml.FXML;
import javafx.scene.control.Label;
-import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import seedu.address.model.person.Person;
@@ -38,9 +35,6 @@ public class PersonCard extends UiPart {
private Label address;
@FXML
private Label email;
- @FXML
- private FlowPane tags;
-
@FXML
private Label remark;
@@ -64,8 +58,5 @@ public PersonCard(Person person, int displayedIndex) {
email.setText(person.getEmail().value);
role.setText(person.getRole());
roleId.setText("ID: " + String.valueOf(person.getId()));
- person.getTags().stream()
- .sorted(Comparator.comparing(tag -> tag.tagName))
- .forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
}
}
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
index a04a490c3e1..a0ba7c2f075 100644
--- a/src/main/resources/view/DarkTheme.css
+++ b/src/main/resources/view/DarkTheme.css
@@ -1,6 +1,5 @@
.background {
-fx-background-color: derive(#ffffff, -20%);
- background-color: #e0e0e0; /* Bright background */
}
.label {
@@ -301,4 +300,4 @@
.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow {
-fx-padding: 1 8
-
+}
diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/seedu/address/commons/core/index/IndexTest.java
deleted file mode 100644
index fc395ab964b..00000000000
--- a/src/test/java/seedu/address/commons/core/index/IndexTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.commons.core.index;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class IndexTest {
-
- @Test
- public void createOneBasedIndex() {
- // invalid index
- assertThrows(IndexOutOfBoundsException.class, () -> Index.fromOneBased(0));
-
- // check equality using the same base
- assertEquals(1, Index.fromOneBased(1).getOneBased());
- assertEquals(5, Index.fromOneBased(5).getOneBased());
-
- // convert from one-based index to zero-based index
- assertEquals(0, Index.fromOneBased(1).getZeroBased());
- assertEquals(4, Index.fromOneBased(5).getZeroBased());
- }
-
- @Test
- public void createZeroBasedIndex() {
- // invalid index
- assertThrows(IndexOutOfBoundsException.class, () -> Index.fromZeroBased(-1));
-
- // check equality using the same base
- assertEquals(0, Index.fromZeroBased(0).getZeroBased());
- assertEquals(5, Index.fromZeroBased(5).getZeroBased());
-
- // convert from zero-based index to one-based index
- assertEquals(1, Index.fromZeroBased(0).getOneBased());
- assertEquals(6, Index.fromZeroBased(5).getOneBased());
- }
-
- @Test
- public void equals() {
- final Index fifthPersonIndex = Index.fromOneBased(5);
-
- // same values -> returns true
- assertTrue(fifthPersonIndex.equals(Index.fromOneBased(5)));
- assertTrue(fifthPersonIndex.equals(Index.fromZeroBased(4)));
-
- // same object -> returns true
- assertTrue(fifthPersonIndex.equals(fifthPersonIndex));
-
- // null -> returns false
- assertFalse(fifthPersonIndex.equals(null));
-
- // different types -> returns false
- assertFalse(fifthPersonIndex.equals(5.0f));
-
- // different index -> returns false
- assertFalse(fifthPersonIndex.equals(Index.fromOneBased(1)));
- }
-
- @Test
- public void toStringMethod() {
- Index index = Index.fromZeroBased(0);
- String expected = Index.class.getCanonicalName() + "{zeroBasedIndex=" + index.getZeroBased() + "}";
- assertEquals(expected, index.toString());
- }
-}
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java
index d203528e7c5..5fbd006927b 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/address/logic/LogicManagerTest.java
@@ -153,7 +153,7 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath)
// Triggers the saveAddressBook method by executing an add command
String createPatientCommand = CreatePatientCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY
+ EMAIL_DESC_AMY + ADDRESS_DESC_AMY;
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
+ Person expectedPerson = new PersonBuilder(AMY).build();
ModelManager expectedModel = new ModelManager();
expectedModel.addPerson(expectedPerson);
assertCommandFailure(createPatientCommand, CommandException.class, expectedMessage, expectedModel);
diff --git a/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java b/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java
index ee5a14a3107..38e284ccd69 100644
--- a/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java
@@ -2,7 +2,7 @@
import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
-//import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.Assert.assertThrows;
import java.nio.file.Path;
import java.time.LocalDateTime;
@@ -11,9 +11,11 @@
import org.junit.jupiter.api.Test;
+import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
-//import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
@@ -42,26 +44,65 @@ public void execute_appointmentAcceptedByModel_addSuccessful() throws Exception
assertEquals(AddAppointmentCommand.MESSAGE_ADD_APPOINTMENT_SUCCESS,
commandResult.getFeedbackToUser());
- String expectedAppointments = String.format("All appointments for you in the database:\n"
- + "Appointment: Id{id=%1$d} (patient id) "
- + "with Id{id=%2$d} (doctor id). Remarks: "
- + "\n", validPatient.getId(), validDoctor.getId());
+ }
- // assertEquals(expectedAppointments, validDoctor.getAllAppointments()); TODO
+ @Test
+ public void execute_duplicateAppointment_throwsCommandException() {
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ validPatient.addAppointment(defaultTime, validPatient.getId(), validDoctor.getId(), defaultRemark);
+ AddAppointmentCommand addAppointmentCommand = new AddAppointmentCommand(defaultTime,
+ validPatient.getId(), validDoctor.getId(), defaultRemark);
+ AddAppointmentCommandTest.ModelStub modelStub = new AddAppointmentCommandTest
+ .ModelStubWithAppointment(validPatient, validDoctor);
+
+ assertThrows(CommandException.class, AddAppointmentCommand
+ .MESSAGE_UNAVAILABLE_SLOT, () -> addAppointmentCommand.execute(modelStub));
}
- // @Test
- // public void execute_duplicateAppointment_throwsCommandException() {
- // Person validPatient = new PersonBuilder().buildPatient();
- // Person validDoctor = new PersonBuilder().buildDoctor();
- // validPatient.addAppointment(defaultTime, validPatient.getId(), validDoctor.getId(), defaultRemark);
- // AddAppointmentCommand addAppointmentCommand = new AddAppointmentCommand(defaultTime,
- // validPatient.getId(), validDoctor.getId(), defaultRemark);
- // AddAppointmentCommandTest.ModelStub modelStub = new AddAppointmentCommandTest
- // .ModelStubWithAppointment(validPatient, validDoctor);
- //
- // assertThrows(CommandException.class, AddAppointmentCommand
- // .MESSAGE_DUPLICATE_APPOINTMENT, () -> addAppointmentCommand.execute(modelStub));
- // } TODO PLS
+
+ @Test
+ public void execute_addAppointmentWithMultiplePatientID_throwsCommandException() {
+ AddAppointmentCommandTest.ModelStubAcceptingAppointmentAdded modelStub = new AddAppointmentCommandTest
+ .ModelStubAcceptingAppointmentAdded();
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPersonToList(validPatient);
+ modelStub.addPersonToList(validDoctor);
+ AddAppointmentCommand addAppointmentCommand = new AddAppointmentCommand(defaultTime,
+ validPatient.getId(), validPatient.getId(), defaultRemark);
+ assertThrows(CommandException.class, Messages
+ .MESSAGE_MULTIPLE_PATIENT_ID, () -> addAppointmentCommand.execute(modelStub));
+ }
+
+ @Test
+ public void execute_addAppointmentWithMultipleDoctorID_throwsCommandException() {
+ AddAppointmentCommandTest.ModelStubAcceptingAppointmentAdded modelStub = new AddAppointmentCommandTest
+ .ModelStubAcceptingAppointmentAdded();
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPersonToList(validPatient);
+ modelStub.addPersonToList(validDoctor);
+ AddAppointmentCommand addAppointmentCommand = new AddAppointmentCommand(defaultTime,
+ validDoctor.getId(), validDoctor.getId(), defaultRemark);
+ assertThrows(CommandException.class, Messages
+ .MESSAGE_MULTIPLE_DOCTOR_ID, () -> addAppointmentCommand.execute(modelStub));
+ }
+
+ @Test
+ public void execute_addAppointmentWithWrongSequenceID_throwsCommandException() {
+ AddAppointmentCommandTest.ModelStubAcceptingAppointmentAdded modelStub = new AddAppointmentCommandTest
+ .ModelStubAcceptingAppointmentAdded();
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPersonToList(validPatient);
+ modelStub.addPersonToList(validDoctor);
+ AddAppointmentCommand addAppointmentCommand = new AddAppointmentCommand(defaultTime,
+ validDoctor.getId(), validPatient.getId(), defaultRemark);
+ assertThrows(CommandException.class, Messages
+ .MESSAGE_MIXED_SEQUENCE_ID, () -> addAppointmentCommand.execute(modelStub));
+ }
+
+
/**
* A default model stub that have all methods failing.
*/
@@ -100,6 +141,10 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public String getPersonRole(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
@Override
public void setAddressBook(ReadOnlyAddressBook newData) {
@@ -125,7 +170,10 @@ public void deletePerson(Person target) {
public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
}
-
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
@Override
public ObservableList getFilteredPersonList() {
return null;
@@ -174,6 +222,10 @@ public boolean hasPerson(Person person) {
requireNonNull(person);
return person.isSamePerson(patient) || person.isSamePerson(doctor);
}
+ @Override
+ public ObservableList getAllPersons() {
+ return javafx.collections.FXCollections.observableArrayList(patient, doctor);
+ }
@Override
public ObservableList getFilteredPersonList() {
@@ -233,6 +285,10 @@ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
return null;
}
@Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
public ObservableList getFilteredPersonList() {
return javafx.collections.FXCollections.observableArrayList(personList);
}
diff --git a/src/test/java/seedu/address/logic/commands/AddRemarksCommandTest.java b/src/test/java/seedu/address/logic/commands/AddRemarksCommandTest.java
new file mode 100644
index 00000000000..e90a2d58007
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/AddRemarksCommandTest.java
@@ -0,0 +1,56 @@
+package seedu.address.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Remark;
+
+public class AddRemarksCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validPatientId_success() {
+ Person patientToEdit = model.getFilteredPersonList().get(0);
+ int validPatientId = patientToEdit.getId();
+ String newNotes = "New notes added.";
+ Remark newRemarks = new Remark(newNotes);
+
+ AddRemarksCommand addRemarksCommand = new AddRemarksCommand(validPatientId, newRemarks);
+
+ String expectedMessage = String.format(AddRemarksCommand.MESSAGE_ADD_REMARKS_SUCCESS,
+ newRemarks, validPatientId);
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+
+ Person expectedPatient = expectedModel.getFilteredPersonList().get(0);
+ expectedPatient.addRemarks(newNotes);
+
+ assertCommandSuccess(addRemarksCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidPatientId_throwsCommandException() {
+ int invalidPatientId = 9999;
+ AddRemarksCommand addRemarksCommand = new AddRemarksCommand(invalidPatientId, new Remark("Some notes"));
+ String expectedMessage = "Unable to add remarks! Check the id entered!";
+
+ assertCommandFailure(addRemarksCommand, model, expectedMessage);
+ }
+
+ @Test
+ public void execute_nullNotes_throwsCommandException() {
+ Person patientToEdit = model.getFilteredPersonList().get(0);
+ int validPatientId = patientToEdit.getId();
+
+ assertThrows(NullPointerException.class, () -> new AddRemarksCommand(validPatientId, null));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/CheckAppointmentCommandTest.java b/src/test/java/seedu/address/logic/commands/CheckAppointmentCommandTest.java
new file mode 100644
index 00000000000..c8a858b240f
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/CheckAppointmentCommandTest.java
@@ -0,0 +1,307 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.logic.commands.CheckAppointmentCommand.MESSAGE_NO_APPOINTMENT_FOUND;
+import static seedu.address.logic.commands.CheckAppointmentCommand.MESSAGE_NO_DATE_TIME;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.GuiSettings;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.person.Person;
+import seedu.address.testutil.PersonBuilder;
+
+public class CheckAppointmentCommandTest {
+
+
+ private final LocalDateTime appointmentTime1 = LocalDateTime.of(2024, 12, 31, 12, 0);
+ private final LocalDateTime appointmentTime2 = LocalDateTime.of(2024, 12, 31, 13, 0);
+ private final LocalDate appointmentDate = LocalDate.of(2024, 12, 31);
+ private final String appointmentRemark = "Follow-up check";
+
+ @Test
+ public void execute_validDoctorWithAppointment_returnsAppointments() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+ modelStub.addAppointment(appointmentTime1, validPatient, validDoctor, appointmentRemark);
+ modelStub.addAppointment(appointmentTime2, validPatient, validDoctor, appointmentRemark);
+
+ CheckAppointmentCommand command = new CheckAppointmentCommand(validDoctor.getId(), appointmentDate);
+ CommandResult result = command.execute(modelStub);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ String expectedMessage = String.format("Appointments on %s:\n"
+ + "[Incomplete] Appointment: %s for %s (patient id)" + " "
+ + "with %s (doctor id). Remarks: %s\n"
+ + "[Incomplete] Appointment: %s for %s (patient id)" + " "
+ + "with %s (doctor id). Remarks: %s\n",
+ appointmentDate, appointmentTime1.format(formatter), validPatient.getId(),
+ validDoctor.getId(), appointmentRemark, appointmentTime2.format(formatter),
+ validPatient.getId(), validDoctor.getId(), appointmentRemark);
+
+ assertEquals(expectedMessage, result.getFeedbackToUser());
+ }
+
+ @Test
+ public void execute_doctorWithNoAppointments_throwsCommandException() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+
+ assertThrows(CommandException.class,
+ String.format(MESSAGE_NO_APPOINTMENT_FOUND, validDoctor.getName()), () ->
+ new CheckAppointmentCommand(validDoctor.getId(), appointmentDate).execute(modelStub));
+ }
+
+ @Test
+ public void execute_doctorWithInvalidIndex_throwsCommandException() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validPatient);
+
+ assertThrows(CommandException.class, Messages.MESSAGE_INVALID_ID, () ->
+ new CheckAppointmentCommand(validDoctor.getId(), appointmentDate).execute(modelStub));
+ }
+
+ @Test
+ public void execute_validDoctorWithoutDateTime_throwsCommandException() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+ modelStub.addAppointment(appointmentTime1, validPatient, validDoctor, appointmentRemark);
+ modelStub.addAppointment(appointmentTime2, validPatient, validDoctor, appointmentRemark);
+
+ assertThrows(CommandException.class,
+ String.format(MESSAGE_NO_DATE_TIME, validDoctor.getName()), () ->
+ new CheckAppointmentCommand(validDoctor.getId(), null).execute(modelStub));
+ }
+
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getAddressBookFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBookFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public String getPersonRole(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBook(ReadOnlyAddressBook newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyAddressBook getAddressBook() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return null;
+ }
+
+ @Override
+ public ObservableList getFilteredPersonById(int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ return null; // TODO?
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ }
+ }
+ /**
+ * A Model stub that contains a single person.
+ */
+ private class ModelStubWithAppointment extends CheckAppointmentCommandTest.ModelStub {
+ private final Person patient;
+ private final Person doctor;
+
+ ModelStubWithAppointment(Person patient, Person doctor) {
+ requireNonNull(patient);
+ requireNonNull(doctor);
+ this.patient = patient;
+ this.doctor = doctor;
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return person.isSamePerson(patient) || person.isSamePerson(doctor);
+ }
+
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(patient, doctor);
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return patient.getId() == (id) ? patient : null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return doctor.getId() == (id) ? doctor : null;
+ }
+ }
+
+ /**
+ * A Model stub that always accept the appointment being added.
+ */
+ public class ModelStubAcceptingAppointmentAdded extends CheckAppointmentCommandTest.ModelStub {
+
+ private final ArrayList personList = new ArrayList<>();
+
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return personList.stream().anyMatch(person::isSamePerson);
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ requireNonNull(person);
+ personList.add(person);
+ }
+
+ public void clearList() {
+ personList.clear();
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ // Search for a patient with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ // Search for a doctor with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(personList);
+ }
+ public void addPersonToList(Person person) {
+ personList.add(person);
+ }
+
+ public void addAppointment(LocalDateTime time, Person patient, Person doctor, String remark) {
+ doctor.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ patient.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ }
+ }
+
+}
+
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
index 643a1d08069..feeb0f67bca 100644
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
@@ -3,22 +3,29 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DAY_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
import static seedu.address.testutil.Assert.assertThrows;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.AddressBook;
import seedu.address.model.Model;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Name;
import seedu.address.model.person.NameContainsKeywordsPredicate;
import seedu.address.model.person.Person;
+import seedu.address.model.person.Phone;
+import seedu.address.model.person.Remark;
import seedu.address.testutil.EditPersonDescriptorBuilder;
/**
@@ -30,29 +37,36 @@ public class CommandTestUtil {
public static final String VALID_NAME_BOB = "Bob Choo";
public static final String VALID_PHONE_AMY = "11111111";
public static final String VALID_PHONE_BOB = "22222222";
+ public static final int VALID_ID_AMY = 111;
+ public static final String VALID_REMARK_AMY = "next treatment is the last one";
+ public static final String VALID_REMARK = "first session";
public static final String VALID_EMAIL_AMY = "amy@example.com";
public static final String VALID_EMAIL_BOB = "bob@example.com";
public static final String VALID_ADDRESS_AMY = "Block 312, Amy Street 1";
public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3";
- public static final String VALID_TAG_HUSBAND = "husband";
- public static final String VALID_TAG_FRIEND = "friend";
-
public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
- public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB;
public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB;
- public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND;
- public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND;
+ public static final String ID_DESC_FIRST = " " + PREFIX_ID + "12";
+ public static final String ID_DESC_SECOND = " " + PREFIX_ID + "14";
+ public static final String ID_DESC_THIRD = " " + PREFIX_ID + "16";
+ public static final String INVALID_ID_DESC = " " + PREFIX_ID + "16@#$%";
public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses
- public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags
+ public static final String VALID_APPOINTMENT_TIME_FIRST_DESC = " " + PREFIX_DATE + "2024-12-31 15:23";
+ public static final String VALID_APPOINTMENT_DATE_DESC = " " + PREFIX_DAY_DATE + "2025-12-30";
+ public static final String INVALID_APPOINTMENT_DATE_DESC = " " + PREFIX_DAY_DATE + "30/12/2025"; // wrong format
+ public static final String VALID_APPOINTMENT_DATE = "2025-12-30";
+ public static final String INVALID_APPOINTMENT_TIME_DESC = " " + PREFIX_DATE + "2024";
+ public static final String VALID_APPOINTMENT_TIME_FIRST = "2024-12-31 15:23";
+ public static final String VALID_REMARK_DESC = " " + PREFIX_REMARK + "first session";
public static final String PREAMBLE_WHITESPACE = "\t \r \n";
public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
@@ -60,13 +74,21 @@ public class CommandTestUtil {
public static final EditCommand.EditPersonDescriptor DESC_AMY;
public static final EditCommand.EditPersonDescriptor DESC_BOB;
+ public static final Person PATIENT_AMY = new Person(new Name(VALID_NAME_AMY), "PATIENT",
+ new Phone(VALID_PHONE_AMY), new Email(VALID_EMAIL_AMY),
+ new Address(VALID_ADDRESS_AMY), new Remark(""));
+ public static final Person DOCTOR_AMY = new Person(new Name(VALID_NAME_AMY), "DOCTOR",
+ new Phone(VALID_PHONE_AMY), new Email(VALID_EMAIL_AMY),
+ new Address(VALID_ADDRESS_AMY), new Remark(""));
+
+
static {
DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
.withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_FRIEND).build();
+ .build();
DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
.withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
+ .build();
}
/**
@@ -115,10 +137,23 @@ public static void assertCommandFailure(Command command, Model actualModel, Stri
* Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
* {@code model}'s address book.
*/
- public static void showPersonAtIndex(Model model, Index targetIndex) {
- assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size());
+ public static void showPersonAtIndex(Model model, int targetIndex) {
+ assertTrue(targetIndex < model.getFilteredPersonList().size());
+
+ Person person = model.getFilteredPersonList().get(targetIndex);
+ final String[] splitName = person.getName().fullName.split("\\s+");
+ model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+
+ assertEquals(1, model.getFilteredPersonList().size());
+ }
+ /**
+ * Updates {@code model}'s filtered list to show only the person at the given {@code id} in the
+ * {@code model}'s address book.
+ */
+ public static void showPersonOfId(Model model, int id) {
+ assertTrue(id <= model.getFilteredPersonList().get(model.getFilteredPersonList().size() - 1).getId());
- Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
+ Person person = model.getFilteredPersonById(model.getFilteredPersonList(), id);
final String[] splitName = person.getName().fullName.split("\\s+");
model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
diff --git a/src/test/java/seedu/address/logic/commands/CreateDoctorCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateDoctorCommandTest.java
index 2f50cec45eb..58953f93fcf 100644
--- a/src/test/java/seedu/address/logic/commands/CreateDoctorCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/CreateDoctorCommandTest.java
@@ -12,6 +12,7 @@
import org.junit.jupiter.api.Test;
+import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.logic.Messages;
@@ -85,6 +86,10 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public String getPersonRole(Person person) {
+ return "DOCTOR";
+ }
@Override
public void setAddressBook(ReadOnlyAddressBook newData) {
@@ -110,7 +115,10 @@ public void deletePerson(Person target) {
public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
}
-
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
@Override
public ObservableList getFilteredPersonList() {
return null;
@@ -123,7 +131,7 @@ public ObservableList getFilteredPersonById(int id) {
@Override
public Person getFilteredPersonById(ObservableList allPersons, int id) {
- return null; // TODO?
+ return null;
}
@Override
@@ -222,6 +230,10 @@ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
return null;
}
@Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
public ObservableList getFilteredPersonList() {
return javafx.collections.FXCollections.observableArrayList(personList);
}
diff --git a/src/test/java/seedu/address/logic/commands/CreatePatientCommandTest.java b/src/test/java/seedu/address/logic/commands/CreatePatientCommandTest.java
new file mode 100644
index 00000000000..f2f970a6d35
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/CreatePatientCommandTest.java
@@ -0,0 +1,245 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.logic.commands.CreatePatientCommand.MESSAGE_DUPLICATE_PERSON;
+import static seedu.address.logic.commands.CreatePatientCommand.MESSAGE_SUCCESS;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.GuiSettings;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.person.Person;
+import seedu.address.testutil.PersonBuilder;
+
+public class CreatePatientCommandTest {
+
+ @Test
+ public void executePatientAddSuccessful() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList(); // Clear the list
+
+ Person validPatient = new PersonBuilder().buildPatient();
+
+ CommandResult commandResult = new CreatePatientCommand(validPatient).execute(modelStub);
+
+ assertEquals(String.format(MESSAGE_SUCCESS, validPatient.getId(), Messages.format(validPatient)),
+ commandResult.getFeedbackToUser());
+ }
+
+ @Test
+ public void executeMultiplePatientAddFailure() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validPatient); // Add first patient
+
+ assertThrows(CommandException.class, MESSAGE_DUPLICATE_PERSON, () ->
+ new CreatePatientCommand(validPatient).execute(modelStub));
+ }
+
+
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getAddressBookFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBookFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public String getPersonRole(Person person) {
+ return "PATIENT";
+ }
+
+ @Override
+ public void setAddressBook(ReadOnlyAddressBook newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyAddressBook getAddressBook() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return null;
+ }
+
+ @Override
+ public ObservableList getFilteredPersonById(int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ return null; // TODO?
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ }
+ }
+ /**
+ * A Model stub that contains a single person.
+ */
+ private class ModelStubWithAppointment extends CreatePatientCommandTest.ModelStub {
+ private final Person patient;
+ private final Person doctor;
+
+ ModelStubWithAppointment(Person patient, Person doctor) {
+ requireNonNull(patient);
+ requireNonNull(doctor);
+ this.patient = patient;
+ this.doctor = doctor;
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return person.isSamePerson(patient) || person.isSamePerson(doctor);
+ }
+
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(patient, doctor);
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return patient.getId() == (id) ? patient : null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return doctor.getId() == (id) ? doctor : null;
+ }
+ }
+
+ /**
+ * A Model stub that always accept the appointment being added.
+ */
+ public class ModelStubAcceptingAppointmentAdded extends CreatePatientCommandTest.ModelStub {
+
+ private final ArrayList personList = new ArrayList<>();
+
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return personList.stream().anyMatch(person::isSamePerson);
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ requireNonNull(person);
+ personList.add(person);
+ }
+
+ public void clearList() {
+ personList.clear();
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ // Search for a patient with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ // Search for a doctor with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(personList);
+ }
+ public void addPersonToList(Person person) {
+ personList.add(person);
+ }
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteAppointmentCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteAppointmentCommandTest.java
new file mode 100644
index 00000000000..6dcacea38fe
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/DeleteAppointmentCommandTest.java
@@ -0,0 +1,239 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.GuiSettings;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.person.Person;
+import seedu.address.testutil.PersonBuilder;
+
+public class DeleteAppointmentCommandTest {
+
+ private static final int VALID_PATIENT_ID = 1234;
+ private static final int VALID_DOCTOR_ID = 5678;
+ private static final LocalDateTime VALID_APPOINTMENT_TIME = LocalDateTime.of(2024, 12, 31, 15, 23);
+ private static final String VALID_REMARK = "first appointment";
+ private static final int NON_EXISTENT_PATIENT_ID = 9999;
+ private static final int NON_EXISTENT_DOCTOR_ID = 8888;
+
+ @Test
+ public void execute_validInputs_success() throws Exception {
+ ModelStubWithAppointment modelStub = new ModelStubWithAppointment();
+ Person validPatient = new PersonBuilder().buildPatientWithChosenIdAndAppointment(VALID_PATIENT_ID,
+ VALID_DOCTOR_ID, VALID_APPOINTMENT_TIME, VALID_REMARK);
+ Person validDoctor = new PersonBuilder().buildDoctorWithChosenIdAndAppointment(VALID_PATIENT_ID,
+ VALID_DOCTOR_ID, VALID_APPOINTMENT_TIME, VALID_REMARK);
+
+ modelStub.addPersonToList(validPatient);
+ modelStub.addPersonToList(validDoctor);
+ System.out.println(modelStub.personList);
+ DeleteAppointmentCommand command = new DeleteAppointmentCommand(VALID_APPOINTMENT_TIME,
+ VALID_PATIENT_ID, VALID_DOCTOR_ID);
+ CommandResult result = command.execute(modelStub);
+
+ assertEquals(DeleteAppointmentCommand.MESSAGE_DELETE_APPOINTMENT_SUCCESS, result.getFeedbackToUser());
+ }
+
+ @Test
+ public void execute_nullAppointmentTime_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () ->
+ new DeleteAppointmentCommand(null, VALID_PATIENT_ID, VALID_DOCTOR_ID));
+ }
+
+ @Test
+ public void execute_nonExistentPatientId_throwsCommandException() {
+ ModelStubWithAppointment modelStub = new ModelStubWithAppointment();
+ Person validDoctor = new PersonBuilder().buildDoctorWithChosenIdAndAppointment(VALID_PATIENT_ID,
+ VALID_DOCTOR_ID, VALID_APPOINTMENT_TIME, VALID_REMARK);
+ modelStub.addPersonToList(validDoctor);
+
+ DeleteAppointmentCommand command = new DeleteAppointmentCommand(VALID_APPOINTMENT_TIME,
+ NON_EXISTENT_PATIENT_ID, VALID_DOCTOR_ID);
+
+ assertThrows(CommandException.class, Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX, () ->
+ command.execute(modelStub));
+ }
+
+ @Test
+ public void execute_nonExistentDoctorId_throwsCommandException() {
+ ModelStubWithAppointment modelStub = new ModelStubWithAppointment();
+ Person validPatient = new PersonBuilder().buildPatientWithChosenIdAndAppointment(VALID_PATIENT_ID,
+ VALID_DOCTOR_ID, VALID_APPOINTMENT_TIME, VALID_REMARK);
+ modelStub.addPersonToList(validPatient);
+ DeleteAppointmentCommand command = new DeleteAppointmentCommand(VALID_APPOINTMENT_TIME,
+ VALID_PATIENT_ID, NON_EXISTENT_DOCTOR_ID);
+ assertThrows(CommandException.class, Messages.MESSAGE_INVALID_DOCTOR_DISPLAYED_INDEX, () ->
+ command.execute(modelStub));
+ }
+
+ // Model Stub to simulate model behavior
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getAddressBookFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBookFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public String getPersonRole(Person person) {
+ return "PATIENT";
+ }
+
+ @Override
+ public void setAddressBook(ReadOnlyAddressBook newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyAddressBook getAddressBook() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredPersonById(int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+ }
+
+ private class ModelStubWithAppointment extends DeleteAppointmentCommandTest.ModelStub {
+ private final ArrayList personList = new ArrayList<>();
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return personList.stream().anyMatch(person::isSamePerson);
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ requireNonNull(person);
+ personList.add(person);
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ Person patient = null;
+ for (Person person : allPersons) {
+ if (person.getId() == id) {
+ patient = person;
+ break;
+ }
+ }
+ return patient;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ Person doctor = null;
+ for (Person person : allPersons) {
+ if (person.getId() == id) {
+ doctor = person;
+ break;
+ }
+ }
+ return doctor;
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(personList);
+ }
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ }
+ public void addPersonToList(Person person) {
+ personList.add(person);
+ }
+
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
new file mode 100644
index 00000000000..0b21ed61437
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
@@ -0,0 +1,107 @@
+package seedu.address.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showPersonOfId;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.person.Person;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code DeleteCommand}.
+ */
+public class DeleteCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validIdUnfilteredList_success() {
+ Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON);
+ DeleteCommand deleteCommand = new DeleteCommand(personToDelete.getId());
+
+ String expectedMessage = DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.deletePerson(personToDelete);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIdUnfilteredList_throwsCommandException() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ int outOfBoundId = model.getFilteredPersonList().get(model.getFilteredPersonList().size() - 1).getId() + 2;
+ DeleteCommand deleteCommand = new DeleteCommand(outOfBoundId);
+
+ assertCommandFailure(deleteCommand, model, DeleteCommand.MESSAGE_DELETE_PERSON_FAILURE);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ showPersonOfId(model, model.getFilteredPersonList().get(INDEX_FIRST_PERSON).getId());
+ Person personToDelete = model.getFilteredPersonById(model.getFilteredPersonList(),
+ model.getFilteredPersonList().get(INDEX_FIRST_PERSON).getId());
+ DeleteCommand deleteCommand = new DeleteCommand(model
+ .getFilteredPersonList().get(INDEX_FIRST_PERSON).getId());
+
+ String expectedMessage = DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS;
+
+ Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.deletePerson(personToDelete);
+ showNoPerson(expectedModel);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void equals() {
+ DeleteCommand deleteFirstCommand = new DeleteCommand(ID_FIRST_PERSON);
+ DeleteCommand deleteSecondCommand = new DeleteCommand(ID_SECOND_PERSON);
+
+ // same object -> returns true
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
+
+ // same values -> returns true
+ DeleteCommand deleteFirstCommandCopy = new DeleteCommand(ID_FIRST_PERSON);
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(deleteFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(deleteFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
+ }
+
+ @Test
+ public void toStringMethod() {
+ int targetId = 1;
+ DeleteCommand deleteCommand = new DeleteCommand(targetId);
+ String expected = DeleteCommand.class.getCanonicalName() + "{person Id=" + targetId + "}";
+ assertEquals(expected, deleteCommand.toString());
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoPerson(Model model) {
+ model.updateFilteredPersonList(p -> false);
+
+ assertTrue(model.getFilteredPersonList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
index 469dd97daa7..28a924cb530 100644
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
@@ -1,23 +1,21 @@
package seedu.address.logic.commands;
-import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import org.junit.jupiter.api.Test;
-import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.model.AddressBook;
@@ -37,11 +35,15 @@ public class EditCommandTest {
@Test
public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
Person editedPerson = new PersonBuilder().build();
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);
+ EditCommand editCommand = new EditCommand(model.getFilteredPersonList()
+ .get(INDEX_FIRST_PERSON).getId(), descriptor);
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(
+ EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)
+ );
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
@@ -49,33 +51,17 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() {
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
}
- @Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size());
- Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased());
-
- PersonBuilder personInList = new PersonBuilder(lastPerson);
- Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build();
- EditCommand editCommand = new EditCommand(indexLastPerson, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(lastPerson, editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
@Test
public void execute_noFieldSpecifiedUnfilteredList_success() {
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor());
- Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON);
+ EditCommand editCommand = new EditCommand(model.getFilteredPersonList()
+ .get(INDEX_FIRST_PERSON).getId(), new EditPersonDescriptor());
+
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(
+ EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)
+ );
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
@@ -84,14 +70,17 @@ public void execute_noFieldSpecifiedUnfilteredList_success() {
@Test
public void execute_filteredList_success() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+ Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON);
Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
+ EditCommand editCommand = new EditCommand(model.getFilteredPersonList().get(INDEX_FIRST_PERSON).getId(),
new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(
+ EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)
+ );
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
@@ -99,60 +88,38 @@ public void execute_filteredList_success() {
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
}
+
@Test
public void execute_duplicatePersonUnfilteredList_failure() {
- Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON);
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor);
+ EditCommand editCommand = new EditCommand(model.getFilteredPersonList().get(INDEX_FIRST_PERSON).getId() + 2,
+ descriptor);
assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
}
@Test
public void execute_duplicatePersonFilteredList_failure() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
showPersonAtIndex(model, INDEX_FIRST_PERSON);
// edit person in filtered list into a duplicate in address book
- Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased());
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
+ Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON);
+ EditCommand editCommand = new EditCommand(model.getFilteredPersonList().get(INDEX_FIRST_PERSON).getId(),
new EditPersonDescriptorBuilder(personInList).build());
assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
}
- @Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- /**
- * Edit filtered list where index is larger than size of filtered list,
- * but smaller than size of address book
- */
- @Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- EditCommand editCommand = new EditCommand(outOfBoundIndex,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
@Test
public void equals() {
- final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY);
+ final EditCommand standardCommand = new EditCommand(ID_FIRST_PERSON, DESC_AMY);
// same values -> returns true
EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY);
- EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor);
+ EditCommand commandWithSameValues = new EditCommand(ID_FIRST_PERSON, copyDescriptor);
assertTrue(standardCommand.equals(commandWithSameValues));
// same object -> returns true
@@ -165,20 +132,10 @@ public void equals() {
assertFalse(standardCommand.equals(new ClearCommand()));
// different index -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY)));
+ assertFalse(standardCommand.equals(new EditCommand(ID_SECOND_PERSON, DESC_AMY)));
// different descriptor -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB)));
+ assertFalse(standardCommand.equals(new EditCommand(ID_FIRST_PERSON, DESC_BOB)));
}
-
- @Test
- public void toStringMethod() {
- Index index = Index.fromOneBased(1);
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- EditCommand editCommand = new EditCommand(index, editPersonDescriptor);
- String expected = EditCommand.class.getCanonicalName() + "{index=" + index + ", editPersonDescriptor="
- + editPersonDescriptor + "}";
- assertEquals(expected, editCommand.toString());
- }
-
}
+
diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
index b17c1f3d5c2..615997e335f 100644
--- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
+++ b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
@@ -9,7 +9,6 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import org.junit.jupiter.api.Test;
@@ -51,10 +50,6 @@ public void equals() {
// different address -> returns false
editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build();
assertFalse(DESC_AMY.equals(editedAmy));
-
- // different tags -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(DESC_AMY.equals(editedAmy));
}
@Test
@@ -64,8 +59,8 @@ public void toStringMethod() {
+ editPersonDescriptor.getName().orElse(null) + ", phone="
+ editPersonDescriptor.getPhone().orElse(null) + ", email="
+ editPersonDescriptor.getEmail().orElse(null) + ", address="
- + editPersonDescriptor.getAddress().orElse(null) + ", tags="
- + editPersonDescriptor.getTags().orElse(null) + "}";
+ + editPersonDescriptor.getAddress().orElse(null) + ", remarks="
+ + editPersonDescriptor.getRemarks().orElse(null) + "}";
assertEquals(expected, editPersonDescriptor.toString());
}
}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
index b8b7dbba91a..c5d80b087f5 100644
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
@@ -3,7 +3,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_NAME;
+import static seedu.address.logic.Messages.MESSAGE_MULTIPLE_PERSONS_WITH_THE_SAME_NAME;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.testutil.TypicalPersons.CARL;
import static seedu.address.testutil.TypicalPersons.ELLE;
@@ -56,17 +57,16 @@ public void equals() {
@Test
public void execute_zeroKeywords_noPersonFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
+ String expectedMessage = MESSAGE_INVALID_NAME;
NameContainsKeywordsPredicate predicate = preparePredicate(" ");
FindCommand command = new FindCommand(predicate);
expectedModel.updateFilteredPersonList(predicate);
assertCommandSuccess(command, model, expectedMessage, expectedModel);
assertEquals(Collections.emptyList(), model.getFilteredPersonList());
}
-
@Test
public void execute_multipleKeywords_multiplePersonsFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
+ String expectedMessage = String.format(MESSAGE_MULTIPLE_PERSONS_WITH_THE_SAME_NAME, 3);
NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz");
FindCommand command = new FindCommand(predicate);
expectedModel.updateFilteredPersonList(predicate);
diff --git a/src/test/java/seedu/address/logic/commands/MarkAppointmentCommandTest.java b/src/test/java/seedu/address/logic/commands/MarkAppointmentCommandTest.java
new file mode 100644
index 00000000000..28a742e173a
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/MarkAppointmentCommandTest.java
@@ -0,0 +1,286 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.commons.core.Messages.MESSAGE_NO_APPOINTMENTS_FOUND;
+import static seedu.address.logic.commands.MarkAppointmentCommand.MESSAGE_MARK_APPOINTMENT_SUCCESS;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.GuiSettings;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.person.Person;
+import seedu.address.testutil.PersonBuilder;
+
+public class MarkAppointmentCommandTest {
+
+ private final LocalDateTime appointmentTime1 = LocalDateTime.of(2024, 12, 31, 12, 0);
+ private final String appointmentRemark = "Follow-up check";
+
+ @Test
+ public void execute_markPatientWithNoAppointment_throwsCommandException() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+
+ assertThrows(CommandException.class, MESSAGE_NO_APPOINTMENTS_FOUND, () ->
+ new MarkAppointmentCommand(appointmentTime1, validPatient.getId(),
+ validDoctor.getId()).execute(modelStub));
+ }
+
+ @Test
+ public void execute_markPatientWithAppointment_addSuccessful() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+
+ modelStub.addAppointment(appointmentTime1, validPatient, validDoctor, appointmentRemark);
+ MarkAppointmentCommand command = new MarkAppointmentCommand(appointmentTime1,
+ validPatient.getId(), validDoctor.getId());
+ CommandResult result = command.execute(modelStub);
+ String expected = MESSAGE_MARK_APPOINTMENT_SUCCESS;
+
+ assertEquals(expected, result.getFeedbackToUser());
+ }
+
+ @Test
+ public void execute_patientWithInvalidIndex_throwsCommandException() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+
+ assertThrows(CommandException.class, Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX, () ->
+ new MarkAppointmentCommand(appointmentTime1, validPatient.getId(),
+ validDoctor.getId()).execute(modelStub));
+ }
+
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getAddressBookFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBookFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAddressBook(ReadOnlyAddressBook newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyAddressBook getAddressBook() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public String getPersonRole(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return null;
+ }
+
+ @Override
+ public ObservableList getFilteredPersonById(int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ return null; // TODO?
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return null;
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ }
+ }
+ /**
+ * A Model stub that contains a single person.
+ */
+ private class ModelStubWithAppointment extends MarkAppointmentCommandTest.ModelStub {
+ private final Person patient;
+ private final Person doctor;
+
+ ModelStubWithAppointment(Person patient, Person doctor) {
+ requireNonNull(patient);
+ requireNonNull(doctor);
+ this.patient = patient;
+ this.doctor = doctor;
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return person.isSamePerson(patient) || person.isSamePerson(doctor);
+ }
+
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(patient, doctor);
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return patient.getId() == (id) ? patient : null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return doctor.getId() == (id) ? doctor : null;
+ }
+ }
+
+ /**
+ * A Model stub that always accept the appointment being added.
+ */
+ public class ModelStubAcceptingAppointmentAdded extends MarkAppointmentCommandTest.ModelStub {
+
+ private final ArrayList personList = new ArrayList<>();
+
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return personList.stream().anyMatch(person::isSamePerson);
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ requireNonNull(person);
+ personList.add(person);
+ }
+
+ public void clearList() {
+ personList.clear();
+ }
+
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ // Search for a patient with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ // Search for a doctor with the specified ID
+ for (Person person : allPersons) {
+ if (person.getId() == (id) && person instanceof Person) {
+ return person;
+ }
+ }
+ return null;
+ }
+ @Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return javafx.collections.FXCollections.observableArrayList(personList);
+ }
+ public void addPersonToList(Person person) {
+ personList.add(person);
+ }
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ for (Person person : allPersons) {
+ if (person.getId() == id) {
+ return person;
+ }
+ }
+ return null; // Return null if no person is found with the specified ID
+ }
+
+ public void addAppointment(LocalDateTime time, Person patient, Person doctor, String remark) {
+ doctor.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ patient.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ }
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/ViewHistoryCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewHistoryCommandTest.java
index a6eb245ddc9..6c0b5c66153 100644
--- a/src/test/java/seedu/address/logic/commands/ViewHistoryCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/ViewHistoryCommandTest.java
@@ -1,109 +1,96 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
-//import static org.junit.jupiter.api.Assertions.assertEquals;
-//import static seedu.address.logic.commands.ViewHistoryCommand.MESSAGE_NO_HISTORY_FOUND;
-//import static seedu.address.testutil.Assert.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.testutil.Assert.assertThrows;
import java.nio.file.Path;
import java.time.LocalDateTime;
-//import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.function.Predicate;
-//import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
-//import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.person.Person;
-//import seedu.address.testutil.PersonBuilder;
+import seedu.address.testutil.PersonBuilder;
public class ViewHistoryCommandTest {
- private final LocalDateTime appointmentTime = LocalDateTime.of(2024, 12, 31, 12, 0);
+ private final LocalDateTime appointmentTime1 = LocalDateTime.of(2024, 12, 31, 12, 0);
+ private final LocalDateTime appointmentTime2 = LocalDateTime.of(2024, 12, 31, 13, 0);
private final String appointmentRemark = "Follow-up check";
- // @Test
- // public void execute_viewHistoryWithTime_success() throws Exception {
- // // Create a ModelStub that can accept appointments
- // ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
- // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
- // Person validPatient = new PersonBuilder().buildPatient();
- // Person validDoctor = new PersonBuilder().buildDoctor();
- //
- // // Add doctor and patient to the model
- // modelStub.addPersonToList(validPatient);
- // modelStub.addPersonToList(validDoctor);
- //
- // // Add an appointment to the patient
- // validPatient
- // .addAppointment(appointmentTime, validPatient.getId(), validDoctor.getId(), appointmentRemark);
- //
- // // Execute the ViewHistoryCommand
- // ViewHistoryCommand viewHistoryCommand = new ViewHistoryCommand(validPatient.getId(), appointmentTime);
- // CommandResult commandResult = viewHistoryCommand.execute(modelStub);
- //
- // // Validate that the appointment was retrieved correctly
- // String expectedMessage = String.format("DateTime: %s Appointment: %s (patient id) with %s (doctor id). "
- // + "Remarks: %s", appointmentTime.format(formatter), validPatient.getId(),
- // validDoctor.getId(), appointmentRemark);
- // assertEquals(expectedMessage, commandResult.getFeedbackToUser());
- // } TODO
-
- // @Test
- // public void execute_viewHistoryWithoutTime_success() throws Exception {
- // // Create a ModelStub that can accept appointments
- // ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
- // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
- // Person validPatient = new PersonBuilder().buildPatient();
- // Person validDoctor = new PersonBuilder().buildDoctor();
- //
- // // Add doctor and patient to the model
- // modelStub.addPersonToList(validPatient);
- // modelStub.addPersonToList(validDoctor);
- //
- // // Add multiple appointments to the patient
- // LocalDateTime firstAppointmentTime = LocalDateTime.of(2024, 12, 31, 12, 0);
- // LocalDateTime secondAppointmentTime = LocalDateTime.of(2024, 11, 30, 15, 0);
- //
- // validPatient.addAppointment(firstAppointmentTime, validPatient.getId(),
- // validDoctor.getId(), "First appointment");
- // validPatient.addAppointment(secondAppointmentTime, validPatient.getId(),
- // validDoctor.getId(), "Second appointment");
- //
- // // Execute the ViewHistoryCommand without specifying a time
- // ViewHistoryCommand viewHistoryCommand = new ViewHistoryCommand(validPatient.getId());
- // CommandResult commandResult = viewHistoryCommand.execute(modelStub);
- //
- // // Validate that both appointments are retrieved correctly
- // String expectedMessage = String.format("DateTime: %s Appointment: %s (patient id) "
- // + "with %s (doctor id). Remarks: First appointment\n"
- // + "DateTime: %s Appointment: %s (patient id) "
- // + "with %s (doctor id). Remarks: Second appointment\n",
- // firstAppointmentTime.format(formatter), validPatient.getId(), validDoctor.getId(),
- // secondAppointmentTime.format(formatter), validPatient.getId(), validDoctor.getId());
- //
- // assertEquals(expectedMessage, commandResult.getFeedbackToUser());
- // } TODO
-
- // @Test
- // public void execute_noHistoryFound_throwsCommandException() {
- // // Create a ModelStub that contains a patient without any medical history
- // ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
- // Person validPatient = new PersonBuilder().buildPatient();
- // modelStub.addPersonToList(validPatient);
- //
- // // Execute the ViewHistoryCommand for a patient with no history
- // ViewHistoryCommand viewHistoryCommand = new ViewHistoryCommand(validPatient.getId());
- //
- // // Expect CommandException with the no history found message
- // assertThrows(CommandException.class, MESSAGE_NO_HISTORY_FOUND, () ->
- // viewHistoryCommand.execute(modelStub));
- // } TODO
+ @Test
+ public void execute_validPatientWithHistory_returnsHistory() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+ modelStub.addAppointment(appointmentTime1, validPatient, validDoctor, appointmentRemark);
+ modelStub.addAppointment(appointmentTime2, validPatient, validDoctor, appointmentRemark);
+
+ ViewHistoryCommand command = new ViewHistoryCommand(validPatient.getId(), appointmentTime1);
+ CommandResult result = command.execute(modelStub);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ String expected = String.format("[Incomplete] Appointment: %s for %s (patient id) "
+ + "with %s (doctor id). Remarks: %s",
+ appointmentTime1.format(formatter), validPatient.getId(),
+ validDoctor.getId(), appointmentRemark);
+
+ assertEquals(expected, result.getFeedbackToUser());
+ }
+ @Test
+ public void execute_patientWithInvalidIndex_throwsCommandException() {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+
+ assertThrows(CommandException.class, Messages.MESSAGE_INVALID_ID, () ->
+ new ViewHistoryCommand(validPatient.getId(), appointmentTime1).execute(modelStub));
+ }
+
+ @Test
+ public void execute_validPatientWithoutDateTime_throwsCommandException() throws Exception {
+ ModelStubAcceptingAppointmentAdded modelStub = new ModelStubAcceptingAppointmentAdded();
+ modelStub.clearList();
+
+ Person validPatient = new PersonBuilder().buildPatient();
+ Person validDoctor = new PersonBuilder().buildDoctor();
+ modelStub.addPerson(validDoctor);
+ modelStub.addPerson(validPatient);
+ modelStub.addAppointment(appointmentTime1, validPatient, validDoctor, appointmentRemark);
+ modelStub.addAppointment(appointmentTime2, validPatient, validDoctor, appointmentRemark);
+
+ ViewHistoryCommand command = new ViewHistoryCommand(validPatient.getId(), null);
+ CommandResult result = command.execute(modelStub);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ String expected = String.format("[Incomplete] Appointment: %s for %s (patient id)" + " "
+ + "with %s (doctor id). Remarks: %s\n"
+ + "[Incomplete] Appointment: %s for %s (patient id)" + " "
+ + "with %s (doctor id). Remarks: %s\n",
+ appointmentTime1.format(formatter), validPatient.getId(), validDoctor.getId(), appointmentRemark,
+ appointmentTime2.format(formatter), validPatient.getId(), validDoctor.getId(), appointmentRemark);
+
+ assertEquals(expected, result.getFeedbackToUser());
+ }
private class ModelStub implements Model {
@Override
@@ -140,6 +127,10 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public String getPersonRole(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
@Override
public void setAddressBook(ReadOnlyAddressBook newData) {
@@ -165,7 +156,10 @@ public void deletePerson(Person target) {
public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
}
-
+ @Override
+ public ObservableList getAllPersons() {
+ throw new AssertionError("This method should not be called.");
+ }
@Override
public ObservableList getFilteredPersonList() {
return null;
@@ -178,7 +172,7 @@ public ObservableList getFilteredPersonById(int id) {
@Override
public Person getFilteredPersonById(ObservableList allPersons, int id) {
- return null; // TODO
+ return null; // TODO?
}
@Override
@@ -220,35 +214,39 @@ public ObservableList getFilteredPersonList() {
return javafx.collections.FXCollections.observableArrayList(patient, doctor);
}
- // @Override
- // public Person getFilteredPatientById(ObservableList allPersons, Id id) {
- // return patient.getId().equals(id) ? patient : null;
- // }
- //
- // @Override
- // public Person getFilteredDoctorById(ObservableList allPersons, Id id) {
- // return doctor.getId().equals(id) ? doctor : null;
- // }
+ @Override
+ public Person getFilteredPatientById(ObservableList allPersons, int id) {
+ return patient.getId() == (id) ? patient : null;
+ }
+
+ @Override
+ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
+ return doctor.getId() == (id) ? doctor : null;
+ }
}
/**
* A Model stub that always accept the appointment being added.
*/
public class ModelStubAcceptingAppointmentAdded extends ViewHistoryCommandTest.ModelStub {
- final ArrayList personsAdded = new ArrayList<>();
private final ArrayList personList = new ArrayList<>();
+
@Override
public boolean hasPerson(Person person) {
requireNonNull(person);
- return personsAdded.stream().anyMatch(person::isSamePerson);
+ return personList.stream().anyMatch(person::isSamePerson);
}
@Override
public void addPerson(Person person) {
requireNonNull(person);
- personsAdded.add(person);
+ personList.add(person);
+ }
+
+ public void clearList() {
+ personList.clear();
}
@Override
@@ -273,12 +271,31 @@ public Person getFilteredDoctorById(ObservableList allPersons, int id) {
return null;
}
@Override
+ public ObservableList getAllPersons() {
+ return FXCollections.observableArrayList(personList);
+ }
+ @Override
public ObservableList getFilteredPersonList() {
return javafx.collections.FXCollections.observableArrayList(personList);
}
public void addPersonToList(Person person) {
personList.add(person);
}
+
+ @Override
+ public Person getFilteredPersonById(ObservableList allPersons, int id) {
+ for (Person person : allPersons) {
+ if (person.getId() == id) {
+ return person;
+ }
+ }
+ return null; // Return null if no person is found with the specified ID
+ }
+
+ public void addAppointment(LocalDateTime time, Person patient, Person doctor, String remark) {
+ doctor.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ patient.addAppointment(time, patient.getId(), doctor.getId(), remark);
+ }
}
}
diff --git a/src/test/java/seedu/address/logic/parser/AddAppointmentCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddAppointmentCommandParserTest.java
new file mode 100644
index 00000000000..7aabaffccde
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/AddAppointmentCommandParserTest.java
@@ -0,0 +1,88 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_SECOND;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_APPOINTMENT_TIME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ID_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK_DESC;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.AddAppointmentCommand;
+
+/**
+ * Asserts parsing behavior for AddAppointmentCommandParser.
+ */
+public class AddAppointmentCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddAppointmentCommand.MESSAGE_USAGE);
+ private final AddAppointmentCommandParser parser = new AddAppointmentCommandParser();
+
+ // 1. All valid input
+ @Test
+ public void parse_allFieldsPresent_success() {
+
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND + VALID_APPOINTMENT_TIME_FIRST_DESC
+ + VALID_REMARK_DESC;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ AddAppointmentCommand expectedCommand = new AddAppointmentCommand(LocalDateTime.parse(
+ VALID_APPOINTMENT_TIME_FIRST, formatter), ID_FIRST_PERSON, ID_SECOND_PERSON,
+ VALID_REMARK);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 2. Input is only addA
+ @Test
+ public void parse_commandWordOnly_failure() {
+ String userInput = "addA";
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 3. Id fields are empty
+ @Test
+ public void parse_missingIds_failure() {
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC + VALID_REMARK_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. Valid ids entered but appointment time is empty
+ @Test
+ public void parse_missingDate_failure() {
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND + VALID_REMARK_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 5. Invalid appointment time
+ @Test
+ public void parse_invalidTime_failure() {
+
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC
+ + VALID_REMARK_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid date-time format, please use yyyy-MM-dd HH:mm.");
+ }
+
+ // 6. Invalid id
+ @Test
+ public void parse_invalidId_failure() {
+
+ String userInput = INVALID_ID_DESC + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC + VALID_REMARK_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!");
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/parser/AddRemarksCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddRemarksCommandParserTest.java
new file mode 100644
index 00000000000..507e0761491
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/AddRemarksCommandParserTest.java
@@ -0,0 +1,65 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_REMARK;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_ID;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ID_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK_AMY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.AddRemarksCommand;
+import seedu.address.model.person.Remark;
+
+public class AddRemarksCommandParserTest {
+
+ private AddRemarksCommandParser parser = new AddRemarksCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsAddNotesCommand() {
+ String userInput = " " + PREFIX_ID + VALID_ID_AMY + " " + PREFIX_REMARK + VALID_REMARK_AMY;
+ AddRemarksCommand expectedCommand = new AddRemarksCommand(VALID_ID_AMY, new Remark(VALID_REMARK_AMY));
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidId_throwsParseException() {
+ String userInput = " " + PREFIX_ID + "abc" + " " + PREFIX_REMARK + VALID_REMARK_AMY;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_ID);
+ }
+
+ @Test
+ public void parse_emptyRemarks_throwsParseException() {
+ String userInput = " " + PREFIX_ID + "abc" + " " + PREFIX_REMARK + " ";
+ assertParseFailure(parser, userInput, MESSAGE_EMPTY_REMARK);
+ }
+
+ @Test
+ public void parse_missingRemark_throwsParseException() {
+ String userInput = " " + PREFIX_ID + VALID_ID_AMY;
+ assertParseFailure(parser, userInput,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddRemarksCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_missingId_throwsParseException() {
+ String userInput = " " + PREFIX_REMARK + VALID_REMARK_AMY;
+ assertParseFailure(parser, userInput,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddRemarksCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_duplicatePrefixes_throwsParseException() {
+ String userInput = " " + PREFIX_ID + VALID_ID_AMY + " "
+ + PREFIX_ID + VALID_ID_AMY + " " + PREFIX_REMARK + VALID_REMARK;
+ String expectedMessage = "Multiple values specified for the following single-valued field(s): z/";
+ assertParseFailure(parser, userInput, expectedMessage);
+ }
+}
+
+
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
index c012c18c5fc..d18bb04d396 100644
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
@@ -5,7 +5,7 @@
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
import java.util.Arrays;
import java.util.List;
@@ -39,11 +39,11 @@ public void parseCommand_clear() throws Exception {
@Test
public void parseCommand_edit() throws Exception {
- Person person = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build();
+ Person person = new PersonBuilder().buildWithDefaultId();
+ EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person, ID_FIRST_PERSON).build();
EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " "
- + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
- assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command);
+ + PersonUtil.getEditPersonDescriptorDetails(descriptor));
+ assertEquals(new EditCommand(ID_FIRST_PERSON, descriptor), command);
}
@Test
diff --git a/src/test/java/seedu/address/logic/parser/CheckAppointmentCommandParserTest.java b/src/test/java/seedu/address/logic/parser/CheckAppointmentCommandParserTest.java
new file mode 100644
index 00000000000..e8d44f3146f
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/CheckAppointmentCommandParserTest.java
@@ -0,0 +1,77 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_APPOINTMENT_DATE_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ID_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_DATE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_DATE_DESC;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.CheckAppointmentCommand;
+
+/**
+ * Asserts parsing behavior for AddAppointmentCommandParser.
+ */
+public class CheckAppointmentCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, CheckAppointmentCommand.MESSAGE_USAGE);
+ private final CheckAppointmentCommandParser parser = new CheckAppointmentCommandParser();
+
+ // 1. All valid input
+ @Test
+ public void parse_allFieldsPresent_success() {
+
+ String userInput = ID_DESC_FIRST + VALID_APPOINTMENT_DATE_DESC;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ CheckAppointmentCommand expectedCommand = new CheckAppointmentCommand(ID_FIRST_PERSON, LocalDate.parse(
+ VALID_APPOINTMENT_DATE, formatter));
+ System.out.println(userInput);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 2. Input is only checkA
+ @Test
+ public void parse_commandWordOnly_failure() {
+ String userInput = "checkA";
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 3. id field is empty
+ @Test
+ public void parse_missingIds_failure() {
+ String userInput = VALID_APPOINTMENT_DATE_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. date y/ is empty
+ @Test
+ public void parse_missingDate_failure() {
+ String userInput = ID_DESC_FIRST;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. date is in the wrong format
+ @Test
+ public void parse_dateWrongFormat_failure() {
+ String userInput = ID_DESC_FIRST + INVALID_APPOINTMENT_DATE_DESC;
+ assertParseFailure(parser, userInput, "Invalid date format. Please use yyyy-MM-dd.");
+ }
+
+ // 4. id is in the wrong format
+ @Test
+ public void parse_idWrongFormat_failure() {
+ String userInput = INVALID_ID_DESC + INVALID_APPOINTMENT_DATE_DESC;
+ assertParseFailure(parser, userInput, "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!");
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/CreateDoctorCommandParserTest.java b/src/test/java/seedu/address/logic/parser/CreateDoctorCommandParserTest.java
new file mode 100644
index 00000000000..2ded8a3c939
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/CreateDoctorCommandParserTest.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.CommandTestUtil.DOCTOR_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.CreateDoctorCommand;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Name;
+import seedu.address.model.person.Phone;
+
+public class CreateDoctorCommandParserTest {
+ private CreateDoctorCommandParser parser = new CreateDoctorCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsCreateDoctorCommand() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE + VALID_PHONE_AMY + " "
+ + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY + " ";
+ CreateDoctorCommand expectedCommand = new CreateDoctorCommand(DOCTOR_AMY);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidName_throwsParseException() {
+ String userInput = INVALID_NAME_DESC + " " + PREFIX_PHONE + VALID_PHONE_AMY
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Name.MESSAGE_CONSTRAINTS, CreateDoctorCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidPhone_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + INVALID_PHONE_DESC
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Phone.MESSAGE_CONSTRAINTS, CreateDoctorCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidEmail_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE
+ + VALID_PHONE_AMY + INVALID_EMAIL_DESC + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Email.MESSAGE_CONSTRAINTS, CreateDoctorCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidAddress_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE + VALID_PHONE_AMY
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + INVALID_ADDRESS_DESC;
+ assertParseFailure(parser, userInput, String.format(
+ Address.MESSAGE_CONSTRAINTS, CreateDoctorCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_missingPhone_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_EMAIL + VALID_EMAIL_AMY
+ + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ MESSAGE_INVALID_COMMAND_FORMAT, CreateDoctorCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_duplicatePrefixes_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_NAME + VALID_NAME_BOB
+ + " " + PREFIX_PHONE + VALID_PHONE_AMY + " " + PREFIX_EMAIL + VALID_EMAIL_AMY
+ + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY + " ";
+ String expectedMessage = "Multiple values specified for the following single-valued field(s): n/";
+ assertParseFailure(parser, userInput, expectedMessage);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/CreatePatientCommandParserTest.java b/src/test/java/seedu/address/logic/parser/CreatePatientCommandParserTest.java
new file mode 100644
index 00000000000..ecb8ba08ede
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/CreatePatientCommandParserTest.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.PATIENT_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.CreatePatientCommand;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Name;
+import seedu.address.model.person.Phone;
+
+public class CreatePatientCommandParserTest {
+ private CreatePatientCommandParser parser = new CreatePatientCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsCreatePatientCommand() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE + VALID_PHONE_AMY + " "
+ + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY + " ";
+ CreatePatientCommand expectedCommand = new CreatePatientCommand(PATIENT_AMY);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidName_throwsParseException() {
+ String userInput = INVALID_NAME_DESC + " " + PREFIX_PHONE + VALID_PHONE_AMY
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Name.MESSAGE_CONSTRAINTS, CreatePatientCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidPhone_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + INVALID_PHONE_DESC
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Phone.MESSAGE_CONSTRAINTS, CreatePatientCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidEmail_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE + VALID_PHONE_AMY
+ + INVALID_EMAIL_DESC + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ Email.MESSAGE_CONSTRAINTS, CreatePatientCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_invalidAddress_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_PHONE + VALID_PHONE_AMY
+ + " " + PREFIX_EMAIL + VALID_EMAIL_AMY + INVALID_ADDRESS_DESC;
+ assertParseFailure(parser, userInput, String.format(
+ Address.MESSAGE_CONSTRAINTS, CreatePatientCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_missingPhone_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_EMAIL + VALID_EMAIL_AMY
+ + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
+ assertParseFailure(parser, userInput, String.format(
+ MESSAGE_INVALID_COMMAND_FORMAT, CreatePatientCommand.MESSAGE_USAGE
+ ));
+ }
+
+ @Test
+ public void parse_duplicatePrefixes_throwsParseException() {
+ String userInput = " " + PREFIX_NAME + VALID_NAME_AMY + " " + PREFIX_NAME + VALID_NAME_BOB
+ + " " + PREFIX_PHONE + VALID_PHONE_AMY + " " + PREFIX_EMAIL + VALID_EMAIL_AMY
+ + " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY + " ";
+ String expectedMessage = "Multiple values specified for the following single-valued field(s): n/";
+ assertParseFailure(parser, userInput, expectedMessage);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/DeleteAppointmentCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteAppointmentCommandParserTest.java
new file mode 100644
index 00000000000..64d4cd8252b
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/DeleteAppointmentCommandParserTest.java
@@ -0,0 +1,83 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_SECOND;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_APPOINTMENT_TIME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ID_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST_DESC;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.DeleteAppointmentCommand;
+
+/**
+ * Asserts parsing behavior for AddAppointmentCommandParser.
+ */
+public class DeleteAppointmentCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, DeleteAppointmentCommand.MESSAGE_USAGE);
+ private final DeleteAppointmentCommandParser parser = new DeleteAppointmentCommandParser();
+
+ // 1. All valid input
+ @Test
+ public void parse_allFieldsPresent_success() {
+
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC + ID_DESC_FIRST + ID_DESC_SECOND;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ DeleteAppointmentCommand expectedCommand = new DeleteAppointmentCommand(LocalDateTime.parse(
+ VALID_APPOINTMENT_TIME_FIRST, formatter), ID_FIRST_PERSON, ID_SECOND_PERSON);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 2. Input is only deleteA
+ @Test
+ public void parse_commandWordOnly_failure() {
+ String userInput = "deleteA";
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 3. Id fields are empty
+ @Test
+ public void parse_missingIds_failure() {
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. Valid ids entered but appointment time is empty
+ @Test
+ public void parse_missingDate_failure() {
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 5. Invalid appointment time
+ @Test
+ public void parse_invalidTime_failure() {
+
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid date-time format, please use yyyy-MM-dd HH:mm.");
+ }
+
+ // 5. Invalid id
+ @Test
+ public void parse_invalidId_failure() {
+
+ String userInput = INVALID_ID_DESC + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!");
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
new file mode 100644
index 00000000000..b727f542701
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
@@ -0,0 +1,43 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.DeleteCommand;
+import seedu.address.model.person.Id;
+
+public class DeleteCommandParserTest {
+ private DeleteCommandParser parser = new DeleteCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsDeleteCommand() {
+ String userInput = " " + PREFIX_ID + "2";
+ DeleteCommand expectedCommand = new DeleteCommand(2);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidId_throwsParseException() {
+ String userInput = " " + PREFIX_ID + "222#";
+ assertParseFailure(parser, userInput, Id.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_blankId_throwsParseException() {
+ String userInput = " " + PREFIX_ID + "";
+ assertParseFailure(parser, userInput, Id.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_missingId_throwsParseException() {
+ String userInput = " ";
+ assertParseFailure(parser, userInput, String.format(
+ MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE
+ ));
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
index cc7175172d4..354595c71e6 100644
--- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
@@ -5,36 +5,32 @@
import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_SECOND;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_THIRD;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_THIRD_PERSON;
import org.junit.jupiter.api.Test;
-import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
@@ -42,13 +38,10 @@
import seedu.address.model.person.Email;
import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
import seedu.address.testutil.EditPersonDescriptorBuilder;
public class EditCommandParserTest {
- private static final String TAG_EMPTY = " " + PREFIX_TAG;
-
private static final String MESSAGE_INVALID_FORMAT =
String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE);
@@ -60,7 +53,7 @@ public void parse_missingParts_failure() {
assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
// no field specified
- assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
+ assertParseFailure(parser, " z/0", EditCommand.MESSAGE_NOT_EDITED);
// no index and no field specified
assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
@@ -83,48 +76,42 @@ public void parse_invalidPreamble_failure() {
@Test
public void parse_invalidValue_failure() {
- assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone
- assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email
- assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address
- assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag
+ assertParseFailure(parser, " z/1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name
+ assertParseFailure(parser, " z/1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone
+ assertParseFailure(parser, " z/1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email
+ assertParseFailure(parser, " z/1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address
// invalid phone followed by valid email
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS);
-
- // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited,
- // parsing it together with a valid tag results in error
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
+ assertParseFailure(parser, " z/1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS);
// multiple invalid values, but only the first invalid value is captured
- assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY,
+ assertParseFailure(parser, " z/1" + INVALID_NAME_DESC
+ + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY,
Name.MESSAGE_CONSTRAINTS);
}
@Test
public void parse_allFieldsSpecified_success() {
- Index targetIndex = INDEX_SECOND_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND
- + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND;
+ int targetId = ID_SECOND_PERSON;
+ String userInput = ID_DESC_SECOND + PHONE_DESC_BOB
+ + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY;
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
.withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+ .build();
+ EditCommand expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
}
@Test
public void parse_someFieldsSpecified_success() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY;
+ int targetId = ID_FIRST_PERSON;
+ String userInput = ID_DESC_FIRST + PHONE_DESC_BOB + EMAIL_DESC_AMY;
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
.withEmail(VALID_EMAIL_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+ EditCommand expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
}
@@ -132,77 +119,59 @@ public void parse_someFieldsSpecified_success() {
@Test
public void parse_oneFieldSpecified_success() {
// name
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + NAME_DESC_AMY;
+ int targetId = ID_THIRD_PERSON;
+ String userInput = ID_DESC_THIRD + NAME_DESC_AMY;
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+ EditCommand expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
// phone
- userInput = targetIndex.getOneBased() + PHONE_DESC_AMY;
+ userInput = ID_DESC_THIRD + PHONE_DESC_AMY;
descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
+ expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
// email
- userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY;
+ userInput = ID_DESC_THIRD + EMAIL_DESC_AMY;
descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
+ expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
// address
- userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY;
+ userInput = ID_DESC_THIRD + ADDRESS_DESC_AMY;
descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // tags
- userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND;
- descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
+ expectedCommand = new EditCommand(targetId, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
}
@Test
public void parse_multipleRepeatedFields_failure() {
// More extensive testing of duplicate parameter detections is done in
- // AddCommandParserTest#parse_repeatedNonTagValue_failure()
// valid followed by invalid
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB;
+ String userInput = ID_DESC_FIRST + INVALID_PHONE_DESC + PHONE_DESC_BOB;
assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
// invalid followed by valid
- userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + INVALID_PHONE_DESC;
+ userInput = ID_DESC_FIRST + PHONE_DESC_BOB + INVALID_PHONE_DESC;
assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
// mulltiple valid fields repeated
- userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
- + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND
- + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND;
+ userInput = ID_DESC_FIRST + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
+ + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
+ + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB;
assertParseFailure(parser, userInput,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS));
// multiple invalid values
- userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC
+ userInput = ID_DESC_FIRST + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC
+ INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC;
assertParseFailure(parser, userInput,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS));
}
- @Test
- public void parse_resetTags_success() {
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + TAG_EMPTY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
}
diff --git a/src/test/java/seedu/address/logic/parser/MarkAppointmentCommandParserTest.java b/src/test/java/seedu/address/logic/parser/MarkAppointmentCommandParserTest.java
new file mode 100644
index 00000000000..f2604a42762
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/MarkAppointmentCommandParserTest.java
@@ -0,0 +1,83 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_SECOND;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_APPOINTMENT_TIME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ID_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST_DESC;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.ID_SECOND_PERSON;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.MarkAppointmentCommand;
+
+/**
+ * Asserts parsing behavior for AddAppointmentCommandParser.
+ */
+public class MarkAppointmentCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, MarkAppointmentCommand.MESSAGE_USAGE);
+ private final MarkAppointmentCommandParser parser = new MarkAppointmentCommandParser();
+
+ // 1. All valid input
+ @Test
+ public void parse_allFieldsPresent_success() {
+
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC + ID_DESC_FIRST + ID_DESC_SECOND;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ MarkAppointmentCommand expectedCommand = new MarkAppointmentCommand(LocalDateTime.parse(
+ VALID_APPOINTMENT_TIME_FIRST, formatter), ID_FIRST_PERSON, ID_SECOND_PERSON);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 2. Input is only deleteA
+ @Test
+ public void parse_commandWordOnly_failure() {
+ String userInput = "deleteA";
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 3. Id fields are empty
+ @Test
+ public void parse_missingIds_failure() {
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. Valid ids entered but appointment time is empty
+ @Test
+ public void parse_missingDate_failure() {
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 5. Invalid appointment time
+ @Test
+ public void parse_invalidTime_failure() {
+
+ String userInput = ID_DESC_FIRST + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid date-time format, please use yyyy-MM-dd HH:mm.");
+ }
+
+ // 5. Invalid id
+ @Test
+ public void parse_invalidId_failure() {
+
+ String userInput = INVALID_ID_DESC + ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!");
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
index 4256788b1a7..f60d9f60739 100644
--- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
+++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
@@ -1,15 +1,8 @@
package seedu.address.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
import org.junit.jupiter.api.Test;
@@ -18,42 +11,27 @@
import seedu.address.model.person.Email;
import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
public class ParserUtilTest {
private static final String INVALID_NAME = "R@chel";
private static final String INVALID_PHONE = "+651234";
private static final String INVALID_ADDRESS = " ";
private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
private static final String VALID_NAME = "Rachel Walker";
private static final String VALID_PHONE = "123456";
private static final String VALID_ADDRESS = "123 Main Street #0505";
private static final String VALID_EMAIL = "rachel@example.com";
- private static final String VALID_TAG_1 = "friend";
- private static final String VALID_TAG_2 = "neighbour";
-
private static final String WHITESPACE = " \t\r\n";
- @Test
- public void parseIndex_invalidInput_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
- }
- @Test
- public void parseIndex_outOfRangeInput_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
- -> ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
- }
@Test
- public void parseIndex_validInput_success() throws Exception {
+ public void parseId_validInput_success() throws Exception {
// No whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
+ assertEquals(ID_FIRST_PERSON, ParserUtil.parsePersonId("12"));
// Leading and trailing whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
+ assertEquals(ID_FIRST_PERSON, ParserUtil.parsePersonId(" 12 "));
}
@Test
@@ -148,49 +126,5 @@ public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exc
assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace));
}
- @Test
- public void parseTag_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null));
- }
-
- @Test
- public void parseTag_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTag(INVALID_TAG));
- }
-
- @Test
- public void parseTag_validValueWithoutWhitespace_returnsTag() throws Exception {
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(VALID_TAG_1));
- }
-
- @Test
- public void parseTag_validValueWithWhitespace_returnsTrimmedTag() throws Exception {
- String tagWithWhitespace = WHITESPACE + VALID_TAG_1 + WHITESPACE;
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(tagWithWhitespace));
- }
-
- @Test
- public void parseTags_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
- }
- @Test
- public void parseTags_collectionWithInvalidTags_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
- }
-
- @Test
- public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
- assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
- }
-
- @Test
- public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception {
- Set actualTagSet = ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, VALID_TAG_2));
- Set expectedTagSet = new HashSet(Arrays.asList(new Tag(VALID_TAG_1), new Tag(VALID_TAG_2)));
-
- assertEquals(expectedTagSet, actualTagSet);
- }
}
diff --git a/src/test/java/seedu/address/logic/parser/ViewHistoryCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ViewHistoryCommandParserTest.java
new file mode 100644
index 00000000000..c547cf3db1b
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/ViewHistoryCommandParserTest.java
@@ -0,0 +1,84 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.ID_DESC_SECOND;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_APPOINTMENT_TIME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ID_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_APPOINTMENT_TIME_FIRST_DESC;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.ID_FIRST_PERSON;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.ViewHistoryCommand;
+
+/**
+ * Asserts parsing behavior for ViewHistoryCommandParserTest.
+ */
+public class ViewHistoryCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, ViewHistoryCommand.MESSAGE_USAGE);
+ private final ViewHistoryCommandParser parser = new ViewHistoryCommandParser();
+
+ // 1. All valid input
+ @Test
+ public void parse_allFieldsPresent_success() {
+
+ String userInput = ID_DESC_FIRST + VALID_APPOINTMENT_TIME_FIRST_DESC;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+
+ ViewHistoryCommand expectedCommand = new ViewHistoryCommand(ID_FIRST_PERSON, LocalDateTime.parse(
+ VALID_APPOINTMENT_TIME_FIRST, formatter));
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 2. Input is only view
+ @Test
+ public void parse_commandWordOnly_failure() {
+ String userInput = "view";
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 3. Id field is empty
+ @Test
+ public void parse_missingIds_failure() {
+ String userInput = VALID_APPOINTMENT_TIME_FIRST_DESC;
+ assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT);
+ }
+
+ // 4. Valid id entered but appointment time is empty
+ @Test
+ public void parse_missingDate_failure() {
+ String userInput = ID_DESC_FIRST;
+ ViewHistoryCommand expectedCommand = new ViewHistoryCommand(ID_FIRST_PERSON, null);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ // 5. Invalid appointment time
+ @Test
+ public void parse_invalidTime_failure() {
+
+ String userInput = ID_DESC_SECOND + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid date-time format, please use yyyy-MM-dd HH:mm.");
+ }
+
+ // 5. Invalid id
+ @Test
+ public void parse_invalidId_failure() {
+
+ String userInput = INVALID_ID_DESC + INVALID_APPOINTMENT_TIME_DESC;
+
+ assertParseFailure(parser, userInput, "Invalid ID entered! Check the ID that you have entered! "
+ + "Make sure the ID is valid!");
+ }
+
+}
+
diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java
index 68c8c5ba4d5..87e63f4b59c 100644
--- a/src/test/java/seedu/address/model/AddressBookTest.java
+++ b/src/test/java/seedu/address/model/AddressBookTest.java
@@ -4,7 +4,6 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import static seedu.address.testutil.Assert.assertThrows;
import static seedu.address.testutil.TypicalPersons.ALICE;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
@@ -46,7 +45,7 @@ public void resetData_withValidReadOnlyAddressBook_replacesData() {
@Test
public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
// Two persons with the same identity fields
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
+ Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB)
.build();
List newPersons = Arrays.asList(ALICE, editedAlice);
AddressBookStub newData = new AddressBookStub(newPersons);
@@ -73,7 +72,7 @@ public void hasPerson_personInAddressBook_returnsTrue() {
@Test
public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() {
addressBook.addPerson(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
+ Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB)
.build();
assertTrue(addressBook.hasPerson(editedAlice));
}
diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java
index 7c1058d8635..2dae8fe6ea5 100644
--- a/src/test/java/seedu/address/model/person/PersonTest.java
+++ b/src/test/java/seedu/address/model/person/PersonTest.java
@@ -6,8 +6,6 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
import static seedu.address.testutil.TypicalPersons.ALICE;
import static seedu.address.testutil.TypicalPersons.BOB;
@@ -17,11 +15,6 @@
public class PersonTest {
- @Test
- public void asObservableList_modifyList_throwsUnsupportedOperationException() {
- Person person = new PersonBuilder().build();
- assertThrows(UnsupportedOperationException.class, () -> person.getTags().remove(0));
- }
@Test
public void isSamePerson() {
@@ -41,16 +34,16 @@ public void isSamePerson() {
// same name, same phone, different attributes -> returns true
editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
+ .build();
assertTrue(ALICE.isSamePerson(editedAlice));
// same name, same email, different attributes -> returns true
editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
+ .build();
assertTrue(ALICE.isSamePerson(editedAlice));
// same name, same phone, same email, different attributes -> returns true
- editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build();
+ editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build();
assertTrue(ALICE.isSamePerson(editedAlice));
}
@@ -88,8 +81,6 @@ public void equals() {
editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build();
assertFalse(ALICE.equals(editedAlice));
- // different tags -> returns false
- editedAlice = new PersonBuilder(ALICE).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(ALICE.equals(editedAlice));
+
}
}
diff --git a/src/test/java/seedu/address/model/person/UniquePersonListTest.java b/src/test/java/seedu/address/model/person/UniquePersonListTest.java
index 17ae501df08..10069df2333 100644
--- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java
+++ b/src/test/java/seedu/address/model/person/UniquePersonListTest.java
@@ -4,7 +4,6 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import static seedu.address.testutil.Assert.assertThrows;
import static seedu.address.testutil.TypicalPersons.ALICE;
import static seedu.address.testutil.TypicalPersons.BOB;
@@ -42,7 +41,7 @@ public void contains_personInList_returnsTrue() {
@Test
public void contains_personWithSameIdentityFieldsInList_returnsTrue() {
uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
+ Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB)
.build();
assertTrue(uniquePersonList.contains(editedAlice));
}
@@ -85,7 +84,7 @@ public void setPerson_editedPersonIsSamePerson_success() {
@Test
public void setPerson_editedPersonHasSameIdentity_success() {
uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
+ Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB)
.build();
uniquePersonList.setPerson(ALICE, editedAlice);
UniquePersonList expectedUniquePersonList = new UniquePersonList();
diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/seedu/address/model/tag/TagTest.java
deleted file mode 100644
index 64d07d79ee2..00000000000
--- a/src/test/java/seedu/address/model/tag/TagTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package seedu.address.model.tag;
-
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class TagTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Tag(null));
- }
-
- @Test
- public void constructor_invalidTagName_throwsIllegalArgumentException() {
- String invalidTagName = "";
- assertThrows(IllegalArgumentException.class, () -> new Tag(invalidTagName));
- }
-
- @Test
- public void isValidTagName() {
- // null tag name
- assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null));
- }
-
-}
diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
index f39a0441232..3213fe5f266 100644
--- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
+++ b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
@@ -5,10 +5,6 @@
//import static seedu.address.testutil.Assert.assertThrows;
//import static seedu.address.testutil.TypicalPersons.BENSON;
//
-//import java.util.ArrayList;
-//import java.util.List;
-//import java.util.stream.Collectors;
-//
//import org.junit.jupiter.api.Test;
//
//import seedu.address.commons.exceptions.IllegalValueException;
@@ -19,20 +15,16 @@
//
//public class JsonAdaptedPersonTest {
// private static final String INVALID_NAME = "R@chel";
-// private static final String PATIENT_ROLE = "patient";
-// private static final String DOCTOR_ROLE = "doctor";
+// private static final String PATIENT_ROLE = "PATIENT";
+// private static final String DOCTOR_ROLE = "DOCTOR";
// private static final String INVALID_PHONE = "+651234";
// private static final String INVALID_ADDRESS = " ";
// private static final String INVALID_EMAIL = "example.com";
-// private static final String INVALID_TAG = "#friend";
//
// private static final String VALID_NAME = BENSON.getName().toString();
// private static final String VALID_PHONE = BENSON.getPhone().toString();
// private static final String VALID_EMAIL = BENSON.getEmail().toString();
// private static final String VALID_ADDRESS = BENSON.getAddress().toString();
-// private static final List VALID_TAGS = BENSON.getTags().stream()
-// .map(JsonAdaptedTag::new)
-// .collect(Collectors.toList());
//
// @Test
// public void toModelType_validPersonDetails_returnsPerson() throws Exception {
@@ -44,7 +36,7 @@
// public void toModelType_invalidName_throwsIllegalValueException() {
// JsonAdaptedPerson person =
// new JsonAdaptedPerson(INVALID_NAME, PATIENT_ROLE,
-// VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
+// VALID_PHONE, VALID_EMAIL, VALID_ADDRESS);
// String expectedMessage = Name.MESSAGE_CONSTRAINTS;
// assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
// }
@@ -108,14 +100,5 @@
// assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
// }
//
-// @Test
-// public void toModelType_invalidTags_throwsIllegalValueException() {
-// List invalidTags = new ArrayList<>(VALID_TAGS);
-// invalidTags.add(new JsonAdaptedTag(INVALID_TAG));
-// JsonAdaptedPerson person =
-// new JsonAdaptedPerson(VALID_NAME, PATIENT_ROLE,
-// VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags);
-// assertThrows(IllegalValueException.class, person::toModelType);
-// }
//
//}
diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
index d53799fd110..b22e359a3a0 100644
--- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java
+++ b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
@@ -16,10 +16,6 @@ public AddressBookBuilder() {
addressBook = new AddressBook();
}
- public AddressBookBuilder(AddressBook addressBook) {
- this.addressBook = addressBook;
- }
-
/**
* Adds a new {@code Person} to the {@code AddressBook} that we are building.
*/
diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
index 4584bd5044e..53f62a4a5c1 100644
--- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
+++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
@@ -1,16 +1,11 @@
package seedu.address.testutil;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
/**
* A utility class to help with building EditPersonDescriptor objects.
@@ -36,7 +31,19 @@ public EditPersonDescriptorBuilder(Person person) {
descriptor.setPhone(person.getPhone());
descriptor.setEmail(person.getEmail());
descriptor.setAddress(person.getAddress());
- descriptor.setTags(person.getTags());
+ }
+ /**
+ * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details
+ * with the id fixed
+ */
+
+ public EditPersonDescriptorBuilder(Person person, int id) {
+ descriptor = new EditPersonDescriptor();
+ descriptor.setId(id);
+ descriptor.setName(person.getName());
+ descriptor.setPhone(person.getPhone());
+ descriptor.setEmail(person.getEmail());
+ descriptor.setAddress(person.getAddress());
}
/**
@@ -71,15 +78,6 @@ public EditPersonDescriptorBuilder withAddress(String address) {
return this;
}
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code EditPersonDescriptor}
- * that we are building.
- */
- public EditPersonDescriptorBuilder withTags(String... tags) {
- Set tagSet = Stream.of(tags).map(Tag::new).collect(Collectors.toSet());
- descriptor.setTags(tagSet);
- return this;
- }
public EditPersonDescriptor build() {
return descriptor;
diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java
index e7a97c54237..5e1cbfea8d9 100644
--- a/src/test/java/seedu/address/testutil/PersonBuilder.java
+++ b/src/test/java/seedu/address/testutil/PersonBuilder.java
@@ -1,7 +1,6 @@
package seedu.address.testutil;
-import java.util.HashSet;
-import java.util.Set;
+import java.time.LocalDateTime;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
@@ -9,43 +8,39 @@
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.person.Remark;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.util.SampleDataUtil;
/**
* A utility class to help with building Person objects.
*/
public class PersonBuilder {
- public static final String DEFAULT_NAME = "Amy Beeee";
- public static final String DEFAULT_PATIENT_ROLE = "patient";
- public static final String DEFAULT_DOCTOR_ROLE = "doctor";
+ public static final String DEFAULT_NAME = "Amy Bee";
+ public static final int DEFAULT_ID = 12;
+ public static final String DEFAULT_PATIENT_ROLE = "PATIENT";
+ public static final String DEFAULT_DOCTOR_ROLE = "DOCTOR";
public static final String DEFAULT_PHONE = "85355255";
public static final String DEFAULT_EMAIL = "amy@gmail.com";
public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111";
-
public static final String DEFAULT_REMARK = "";
private Name name;
+ private int id;
private String role;
private Phone phone;
private Email email;
private Address address;
private Remark remark;
- private Set tags;
-
- private int id;
/**
* Creates a {@code PersonBuilder} with the default details.
*/
public PersonBuilder() {
name = new Name(DEFAULT_NAME);
+ id = DEFAULT_ID;
role = DEFAULT_PATIENT_ROLE;
phone = new Phone(DEFAULT_PHONE);
email = new Email(DEFAULT_EMAIL);
address = new Address(DEFAULT_ADDRESS);
remark = new Remark(DEFAULT_REMARK);
- tags = new HashSet<>();
}
/**
@@ -58,7 +53,6 @@ public PersonBuilder(Person personToCopy) {
email = personToCopy.getEmail();
address = personToCopy.getAddress();
remark = personToCopy.getRemark();
- tags = new HashSet<>(personToCopy.getTags());
id = personToCopy.getId();
}
@@ -70,14 +64,6 @@ public PersonBuilder withName(String name) {
return this;
}
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code Person} that we are building.
- */
- public PersonBuilder withTags(String ... tags) {
- this.tags = SampleDataUtil.getTagSet(tags);
- return this;
- }
-
/**
* Sets the {@code Address} of the {@code Person} that we are building.
*/
@@ -111,19 +97,45 @@ public PersonBuilder withRemark(String remark) {
}
public Person build() {
- return new Person(name, role, phone, email, address, remark, tags);
+ return new Person(name, role, phone, email, address, remark);
}
+ public Person buildWithDefaultId() {
+ return new Person(name, id, role, phone, email, address, remark);
+ }
+
+
/**
- * builds a patient class
+ * Builds a patient class
*/
public Person buildPatient() {
- return new Person(name, role, phone, email, address, remark, tags);
+ return new Person(name, role, phone, email, address, remark);
+ }
+
+ /**
+ * Builds a patient with a id and appointment added
+ */
+ public Person buildPatientWithChosenIdAndAppointment(int patientId, int doctorId, LocalDateTime appointmentTime,
+ String remarks) {
+ Person newPerson = new Person(name, patientId, DEFAULT_PATIENT_ROLE, phone, email, address, remark);
+ newPerson.addAppointment(appointmentTime, patientId, doctorId, remarks);
+ return newPerson;
}
/**
- * builds a doctor class
+ * Builds a doctor with a id and appointment added
+ */
+ public Person buildDoctorWithChosenIdAndAppointment(int patientId, int doctorId, LocalDateTime appointmentTime,
+ String remarks) {
+ Person newPerson = new Person(name, doctorId, DEFAULT_DOCTOR_ROLE, phone, email, address, remark);
+ newPerson.addAppointment(appointmentTime, patientId, doctorId, remarks);
+ return newPerson;
+ }
+
+ /**
+ * Builds a doctor class
*/
public Person buildDoctor() {
- return new Person(name, DEFAULT_DOCTOR_ROLE, phone, email, address, remark, tags);
+ return new Person(name, DEFAULT_DOCTOR_ROLE, phone, email, address, remark);
}
+
}
diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java
index 26512a9c614..aa1f36184d0 100644
--- a/src/test/java/seedu/address/testutil/PersonUtil.java
+++ b/src/test/java/seedu/address/testutil/PersonUtil.java
@@ -2,15 +2,12 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ID;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.model.person.Person;
-import seedu.address.model.tag.Tag;
/**
* A utility class for Person.
@@ -26,9 +23,6 @@ public static String getPersonDetails(Person person) {
sb.append(PREFIX_PHONE + person.getPhone().value + " ");
sb.append(PREFIX_EMAIL + person.getEmail().value + " ");
sb.append(PREFIX_ADDRESS + person.getAddress().value + " ");
- person.getTags().stream().forEach(
- s -> sb.append(PREFIX_TAG + s.tagName + " ")
- );
return sb.toString();
}
@@ -37,18 +31,11 @@ public static String getPersonDetails(Person person) {
*/
public static String getEditPersonDescriptorDetails(EditPersonDescriptor descriptor) {
StringBuilder sb = new StringBuilder();
+ sb.append(PREFIX_ID).append(descriptor.getId()).append(" ");
descriptor.getName().ifPresent(name -> sb.append(PREFIX_NAME).append(name.fullName).append(" "));
descriptor.getPhone().ifPresent(phone -> sb.append(PREFIX_PHONE).append(phone.value).append(" "));
descriptor.getEmail().ifPresent(email -> sb.append(PREFIX_EMAIL).append(email.value).append(" "));
descriptor.getAddress().ifPresent(address -> sb.append(PREFIX_ADDRESS).append(address.value).append(" "));
- if (descriptor.getTags().isPresent()) {
- Set tags = descriptor.getTags().get();
- if (tags.isEmpty()) {
- sb.append(PREFIX_TAG);
- } else {
- tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" "));
- }
- }
return sb.toString();
}
}
diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/seedu/address/testutil/TestUtil.java
index 896d103eb0b..6b23436c9e3 100644
--- a/src/test/java/seedu/address/testutil/TestUtil.java
+++ b/src/test/java/seedu/address/testutil/TestUtil.java
@@ -5,10 +5,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
-import seedu.address.commons.core.index.Index;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
/**
* A utility class for test cases.
*/
@@ -31,25 +27,4 @@ public static Path getFilePathInSandboxFolder(String fileName) {
}
return SANDBOX_FOLDER.resolve(fileName);
}
-
- /**
- * Returns the middle index of the person in the {@code model}'s person list.
- */
- public static Index getMidIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size() / 2);
- }
-
- /**
- * Returns the last index of the person in the {@code model}'s person list.
- */
- public static Index getLastIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size());
- }
-
- /**
- * Returns the person in the {@code model}'s person list at {@code index}.
- */
- public static Person getPerson(Model model, Index index) {
- return model.getFilteredPersonList().get(index.getZeroBased());
- }
}
diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java
index 1e613937657..2d63961cdab 100644
--- a/src/test/java/seedu/address/testutil/TypicalIndexes.java
+++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java
@@ -1,12 +1,13 @@
package seedu.address.testutil;
-import seedu.address.commons.core.index.Index;
-
/**
* A utility class containing a list of {@code Index} objects to be used in tests.
*/
public class TypicalIndexes {
- public static final Index INDEX_FIRST_PERSON = Index.fromOneBased(1);
- public static final Index INDEX_SECOND_PERSON = Index.fromOneBased(2);
- public static final Index INDEX_THIRD_PERSON = Index.fromOneBased(3);
+ public static final int INDEX_FIRST_PERSON = 0;
+ public static final int INDEX_SECOND_PERSON = 1;
+ public static final int INDEX_THIRD_PERSON = 2;
+ public static final int ID_FIRST_PERSON = 12;
+ public static final int ID_SECOND_PERSON = 14;
+ public static final int ID_THIRD_PERSON = 16;
}
diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java
index d0a78f907f2..07ffab16b51 100644
--- a/src/test/java/seedu/address/testutil/TypicalPersons.java
+++ b/src/test/java/seedu/address/testutil/TypicalPersons.java
@@ -8,8 +8,6 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
import java.util.ArrayList;
import java.util.Arrays;
@@ -26,17 +24,17 @@ public class TypicalPersons {
public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
.withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
.withPhone("94351253")
- .withTags("friends").build();
+ .build();
public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
.withAddress("311, Clementi Ave 2, #02-25")
.withEmail("johnd@example.com").withPhone("98765432")
- .withTags("owesMoney", "friends").build();
+ .build();
public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563")
.withEmail("heinz@example.com").withAddress("wall street").buildDoctor();
public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533")
- .withEmail("cornelia@example.com").withAddress("10th street").withTags("friends").build();
+ .withEmail("cornelia@example.com").withAddress("10th street").build();
public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
.withEmail("werner@example.com").withAddress("michegan ave").build();
public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
@@ -52,9 +50,9 @@ public class TypicalPersons {
// Manually added - Person's details found in {@code CommandTestUtil}
public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
- .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
+ .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).build();
public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
+ .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
.build();
public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER