diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 95e8d3c803a..49841d4c839 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -3,7 +3,7 @@ layout: page title: User Guide --- -MediLink Contacts(MLC) is a **desktop app for managing patients and doctors details, optimized for use via a Command +MediLink Contacts (MLC) is a **desktop app for managing patients and doctors details, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, MLC can get your patients management tasks done faster than traditional GUI apps. @@ -19,16 +19,16 @@ can get your patients management tasks done faster than traditional GUI apps. 1. Ensure you have Java `11` or above installed in your Computer. If you don't, install it for your relevant operating system at this link https://www.oracle.com/sg/java/technologies/javase/jdk11-archive-downloads.html -1. Download the latest `MediLink.jar` from [here](https://github.com/AY2324S1-CS2103T-T09-3/tp/releases). +2. Download the latest `MediLink.jar` from [here](https://github.com/AY2324S1-CS2103T-T09-3/tp/releases). -1. Copy the file to the folder you want to use as the _home folder_ for your MLC. +3. Copy the file to the folder you want to use as the _home folder_ for your MLC. -1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar Medilink.jar` command +4. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar MediLink.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.
![Ui](images/Ui.png) -1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will +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: @@ -43,9 +43,27 @@ can get your patients management tasks done faster than traditional GUI apps. * `exit` : Exits the app. -1. Refer to the [Features](#features) below for details of each command. +6. Refer to the [Features](#features) below for details of each command. -------------------------------------------------------------------------------------------------------------------- +## Parameters + +The list below contains the parameters that are used in various commands as well as their various constraints. Failing to input valid parameters will lead to errors when entering commands. + +| Parameter | Constraints | Valid Examples | Invalid Examples | +|:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------|:-----------------------------------| +| NRIC | Starting with S or T, followed by 7 numbers, and ends with a letter. Not case-sensitive. | T0123456G, s33344476i | T01234567G, “”, t12367K | +| Doctor/Patient Name | Empty strings are not allowed. Name must contain only alphanumeric characters. | Cristiano Ronaldo, Tanveer Singh | “”, 高橋紳助, s/o someone | +| Contact Number | 3 digit or more integer as phone number. Empty strings are not allowed. | 91234569 | “”, 99 | +| Email | Must be of the format `local-name`@`domain`. `local-name` should only contain alphanumeric characters and these special characters, excluding the parentheses, (+_.-), and may not start or end with any special characters. `domain` is made up of domain labels separated by periods, and must end with a domain label at least 2 characters long. Domain labels start and end with alphanumeric characters, consist of alphanumeric characters, separated only by hyphens, if any. | j@Email.com, isaac@a-b.com | isaac@a+b.com, james.com | +| Blood Type | Accepts only strings containing valid blood types, that is a combination of A/B/AB/O and +/-. Letters must be in caps. | B+, O+, B-, AB+ | J, K, A, O | +| Address | Any non-empty string. | Clementi, OneCare@Hougang Avenue | "" | +| Gender | Either the character “M” or “F”. Must be in caps. | M, F | G, girl, male, f | +| Emergency Contact | Valid Contact number. Same constraints as the Contact Number parameter. | 91234569 | “”, 99 | +| Condition | Any non-empty string. | Knee Injury, appendicitis | "" | +| Patient Tag | Accepts only strings containing valid priority levels, either low, medium or high. Not case-sensitive. | low, MEDIUM, hiGh | extreme, med | +| Doctor Tag | Accepts only strings containing valid specialisations. Not case-sensitive. The current allowed specialisations are listed in the examples box. | CARDIOLOGIST, ORTHOPEDIC, PEDIATRICIAN, DERMATOLOGIST, NEUROLOGIST, GENERAL_PRACTITIONER, PSYCHIATRIST, SURGEON | Nurse, Head-Doctor | +| Time | Accepts only strings that follow the specified format (ie. `yyyy-MM-dd HH:mm`), where `HH:mm` follows the 24hr format. | 2016-10-10 18:00,
2000-01-30 23:59 | 2005-10-32 18:00, 2016-11-02 27:00 | ## Features @@ -76,7 +94,7 @@ can get your patients management tasks done faster than traditional GUI apps. ### Viewing help : `help` -Shows a message explaning how to access the help page. +Shows a message explaining how to access the help page. ![help message](images/helpMessage.png) @@ -84,7 +102,7 @@ Format: `help` ### Adding a Doctor: `add-doctor` -Adds a Doctor to the hospital database. +Adds a Doctor to the clinic database. Format: `add-doctor n/NAME ic/IC g/GENDER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` @@ -96,19 +114,18 @@ A doctor can have any number of tags (including 0). Duplicate tags, however, are **:information_source: Take Note:**
-- A doctor **MUST** have a non-empty NAME and a valid IC at the very least. +- A doctor **MUST** have all fields non-empty except TAG. Failure to include these details may result in an error. +- The order is not important (i.e, IC can come before NAME). What matters is that all the mandatory fields are declared, +and the format for each field is adhered to. - A person can either be a doctor or a patient, but not both. Hence if the doctor's IC is already in the app as a patient, it may result in an error. -- Phone Numbers and Emails have to be in a valid format. -- PHONE_NUMBER must have exactly 8 digits. -- EMAIL must contain email domain (eg. `@gmail.com`). -- PATIENT must contain the valid IC of a Patient in the Database. -- Tags for doctors represent the specialisation(s) of the doctor. Only tags from the list below are supported -in our current version: +- Adding additional prefixes (eg. `b/O+`) not specified by the command format above will be considered as a **parameter input**. For example:
+ `add-doctor n/John Doe ic/S9851386G g/M p/98765432 e/johnd@example.com a/John street, block 123, #01-01 b/O+` will result + in Address inputted as `a/John street, block 123, #01-01 b/O+`.
+ Do avoid adding your own prefixes as it may lead to unwanted errors! +- However, inputting `r/REMARKS` will be ignored and automatically removed by the system. To add remarks, use the Edit Command mentioned later below. - `CARDIOLOGIST, ORTHOPEDIC, PEDIATRICIAN, DERMATOLOGIST, NEUROLOGIST, GENERAL_PRACTITIONER, PSYCHIATRIST, SURGEON` -- Tags are not case-sensitive (e.g. `t/SURGEON` and `t/surgeon` are both valid inputs). Examples: @@ -116,39 +133,91 @@ Examples: * `add-doctor n/John Doe ic/S9851386G g/M p/98765432 e/johnd@example.com a/John street, block 123, #01-01 t/Pediatrician` * `add-doctor n/Betsy Crowe ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon` +
+ +**:information_source: Common Errors:**
+1. Invalid Command Format
+All fields are mandatory except the tag field. Omission of the fields will throw an error stating +that an invalid command has been given, and specify the correct format for the `add-doctor command`.
+Example: `add-doctor ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon`
+Error Message: `Invalid command format!`
+ `add-doctor: Adds a person to the address book. Parameters: n/NAME p/PHONE e/EMAIL a/ADDRESS g/GENDER ic/NRIC [t/TAG]...` +2. Invalid/Empty Field
+ Fields have specific formats to be followed. Failure to adhere to this format will lead to an error message +that specifies the format to be used for that field. Usage of flags without any message will lead to the same +corresponding error message since no field supports empty inputs. + ``` + add-doctor n/ ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon + Names should only contain alphanumeric characters and spaces, and it should not be blank + + add-doctor n/Betsy Crowe ic/999 g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon + Ic should start with S or T, followed by 7 numbers, and ends with a letter. Letters inputs are case-insensitive. Empty strings are not allowed + + add-doctor n/Betsy Crowe ic/S9851586G g/B p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon + Gender should only be M for Male or F for Female + + add-doctor n/Betsy Crowe ic/S9851586G g/F p/phoneNumber e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/Surgeon + Phone numbers should only contain numbers, and it should be at least 3 digits long + + add-doctor n/Betsy Crowe ic/S9851586G g/F p/98765433 e/ a/#104-C, Wakanda St 42 t/Surgeon + Emails should be of the format local-part@domain and adhere to the following constraints: + 1. The local-part should only contain alphanumeric characters and these special characters, excluding the parentheses, (+_.-). The local-part may not start or end with any special characters. + 2. This is followed by a '@' and then a domain name. The domain name is made up of domain labels separated by periods. + The domain name must: + - end with a domain label at least 2 characters long + - have each domain label start and end with alphanumeric characters + - have each domain label consist of alphanumeric characters, separated only by hyphens, if any. + + add-doctor n/Betsy Crowe ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/ t/Surgeon + Addresses can take any values, and it should not be blank + + add-doctor n/Betsy Crowe ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/BestDoctor + Doctor tag should be a valid specialisation. + ``` +3. Adding custom prefixes
+Adding custom prefixes will mostly cause the preceding flag to become invalid.
+Exceptions: + * Adding 'custom' flags to the address or condition field will, however, be accepted as +Addresses may involve the usage of the `/` character. Hence, take note to use the address field carefully. + * Adding the 'custom' flag before any other field will recognise the input to be of Invalid Command Format. +
+Examples: + * `add-doctor pic/ n/Faiz ic/S9851486G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/surgeon` + * `add-doctor n/Faiz pic/ ic/S9851486G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/surgeon` + * `add-doctor n/Faiz ic/S9851486G g/F p/98765433 e/betsycrowe@example.com a/#104/C, Wakanda St 42 t/surgeon` +4. Special Cases
+Names with special characters may not adhere to the current format for names, and may be recognised as an invalid input. +Example: + * `add-doctor n/David s/o Beckham ic/S9851486G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 t/surgeon` +
+ ### Adding a Patient: `add-patient` -Adds a Patient to the hospital database. +Adds a Patient to the clinic database. -Format: `add-patient n/NAME ic/IC g/GENDER p/PHONE_NUMBER ec/EMERGENCY_CONTACT e/EMAIL a/ADDRESS [t/TAG] [d/DOCTOR] [c/CONDITION] [b/BLOODTYPE] ​` +Format: `add-patient n/NAME ic/IC g/GENDER p/PHONE_NUMBER ec/EMERGENCY_CONTACT e/EMAIL a/ADDRESS c/CONDITION b/BLOODTYPE [t/TAG] ​`
**:information_source: Take Note:**
-- A patient **MUST** have a non-empty NAME and a valid IC at the very least. Failure to include these details may result - in an error. +- A patient cannot have the same NRIC as another person. - A person can either be a doctor or a patient, but not both. Hence, if the patient's IC is already in the app as a doctor, it may result in an error. -- Phone Numbers and Emails have to be in a valid format. - - PHONE_NUMBER must have at least 3 digits - - EMAIL must contain email domain (eg. `@gmail.com`). -- TAG must indicate Priority Level of the Patient and be one of the following: - - Low - - Medium - - High -- EMERGENCY_CONTACT must contain valid emergency contact number, which needs to be a valid phone number. -- Blood type must be a combination of A/B/AB/O and +/-. +- EMERGENCY_CONTACT must contain valid emergency contact number, which needs to be a valid phone number. This number can be the same the person's contact number. - A patient can only have up to one tag at any time. -- Tags for patients represent the priority level of the patient. Only the following tags are allowed: Low, Medium, High. -- Tags are not case-sensitive (e.g. `t/LOW` and `t/low` are both valid inputs). +- Adding additional prefixes (eg. `k/Always Injured`) not specified by the command format above will be considered as a **parameter input**. For example:
+ `add-patient n/John Doe ic/S9851386G g/M p/98765432 ec/90123456 e/johnd@example.com a/John street, block 123, #01-01 c/pneumothorax k/Always Injured b/O+` will result + in Condition inputted as `pneumothorax k/Always Injured`.
+ Do avoid adding your own prefixes as it may lead to unwanted errors! +- However, inputting `r/REMARKS` will be ignored and automatically removed by the system. To add remarks, use the Edit Command mentioned later below.
Examples: * `add-patient n/John Doe ic/S9851386G g/M p/98765432 ec/90123456 e/johnd@example.com a/John street, block 123, #01-01 c/pneumothorax b/O+ t/Low` -* `add-patient n/Betsy Crowe ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 c/AIDS b/O+ t/High` +* `add-patient n/Betsy Crowe ic/S9851586G g/F p/98765433 ec/12345678 e/betsycrowe@example.com a/#104-C, Wakanda St 42 c/AIDS b/O+ t/High` ### Creating an Appointment : `new-appt` @@ -160,10 +229,9 @@ Format: `new-appt pic/IC dic/IC time/yyyy-MM-dd HH:mm` **:information_source: Take Note:**
- All fields are Required. -- TIME must follow the specified format (ie. `yyyy-MM-dd HH:mm`), where `HH:mm` follows the 24hr format. - PATIENT must contain the valid IC of a Patient in the Database. - DOCTOR must contain the valid IC of a Doctor in the Database. -- There must not be conflicting Appointments (eg the doctor already has an appointment with another patient at the same time) +- There must not be conflicting Appointments. (eg. the doctor already has an appointment with another patient at the same time) However, the duration of each appointment is flexible and up to the users. As long as appointments are not at the exact same time, users can add it in. @@ -211,7 +279,7 @@ Examples: ### Listing all persons : `list` -Shows a list of all persons in the MediLink Contacts. +Shows a list of all persons and appointments in the MediLink Contacts. Format: `list` @@ -221,22 +289,22 @@ Edits an existing person in the MediLink Contacts. Format: `edit NRIC [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` -* Edits the person at the specified `NRIC`. The NRIC **must be a valid IC number** +* Edits the person with the specified `NRIC`. The NRIC **must be a valid IC number** * At least one of the optional fields must be provided. * If the provided fields are the same as the original, the command will still work. * Must edit appropriate fields based on whether the person is a patient or doctor (e.g. can't update condition of a - doctor) + doctor). * 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. -* Note: In our app, the Remark Section will be left blank by default. Edit Command can be used to add any misc info not captured by other fields such as possible allergies, medical history, etc. +* Note: In our app, the Remark Section will be left blank by default. The edit Command can be used to add any miscellaneous info not captured by other fields such as possible allergies, medical history, etc. Examples: -* `edit T0123456A p/91234567 e/johndoe@example.com g/F` Edits the phone number and email address of the 1st person to +* `edit T0123456A p/91234567 e/johndoe@example.com g/F` edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit S9876543B n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all +* `edit S9876543B n/Betsy Crower t/` edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. ### Locating persons by name: `find` @@ -245,42 +313,42 @@ Finds persons that match the query. Format: `find KEYWORD [MORE_KEYWORDS]` -* When searching names, the search is case-insensitive. e.g `hans` will match `Hans` -* When searching names, the order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* When searching names, only full words will be matched e.g. `Han` will not match `Hans` +* When searching names, the search is case-insensitive. e.g `hans` will match `Hans`. +* When searching names, the order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`. +* When searching names, only full words will be matched e.g. `Han` will not match `Hans`. * When searching names, Persons matching at least one keyword will be returned (i.e. `OR` search). - e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` + e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`. * Note that if the name coincides with other find commands, it will be interpreted as the other find command first and extraneous paremeters will be ignored. e.g. `find F Kennedy John` will search for all female persons. -* It is recommended to use `list` to restore the view of all data after a `find` command +* It is recommended to use `list` to restore the view of all data after a `find` command. Examples: -* `find John` returns `john` and `John Doe` -* `find kenny pickens` returns `Kenny Pickett`, `George Pickens`
+* `find John` returns `john` and `John Doe`. +* `find kenny pickens` returns `Kenny Pickett`, `George Pickens`.
![result for 'find alex david'](images/findpickettpickensresult.png) ### Locating a person by NRIC : `find` ### -Finds person that matches the NRIC query +Finds person that matches the NRIC query. Format: `find NRIC` * NRIC input must be capitalised! -* It is recommended to use `list` to restore the view of all data after a `find` command +* It is recommended to use `list` to restore the view of all data after a `find` command. Examples: -* `find T1125726G` returns the person with the matching NRIC +* `find T1125726G` returns the person with the matching NRIC. ### Locating people by gender : `find M`, `find F` ### -Finds all persons with matching gender +Finds all persons with matching gender. Format: `find M` or `find F` -* M and F must be capitalised -* It is recommended to use `list` to restore the view of all data after a `find` command +* M and F must be capitalised. +* It is recommended to use `list` to restore the view of all data after a `find` command. Examples: @@ -288,17 +356,15 @@ Examples: ### Locating people by blood types : `find Blood Type` ### -Finds all Patients with query blood type +Finds all Patients with query blood type. Format: `find Blood Type QUERY` -* All blood type inputs must be capitalised -* Acceptable blood types are A, A+, B, B+, O, O+, AB and AB+ -* It is recommended to use `list` to restore the view of all data after a `find` command +* It is recommended to use `list` to restore the view of all data after a `find` command. Examples: -* `find Blood Type A+` returns all Patients with blood type A+ +* `find Blood Type A+` returns all Patients with blood type A+. ### Deleting a person : `delete` @@ -307,12 +373,10 @@ Deletes the specified person from the address book. Format: `delete NRIC` * Deletes the person with the specified NRIC. -* The NRIC **must be a valid NRIC format** and must belong to a person in the addressbook. -* The NRIC is case-sensitive. e.g `tXXXXXXXz` is not the same as `TXXXXXXXZ` Examples: -* `delete S1234567J` deletes Jonathan who has the NRIC `S1234567J` +* `delete S1234567J` deletes Jonathan who has the NRIC `S1234567J`. ### Clearing all entries : `clear` @@ -322,6 +386,13 @@ Format: `clear` ### Undo last action : `undo` +
+**:information_source: Take Note:**
+ +- Upon restarting the app, you will no longer be able to undo actions previously performed before exiting the app. + +
+ Undoes the effect of the last command. Format: `undo` @@ -330,7 +401,14 @@ Format: `undo` ### Redo last action : `redo` -Repeats the previous command; an `undo` for an `undo` command. +
+**:information_source: Take Note:**
+ +- Upon restarting the app, you will no longer be able to redo actions previously undone before exiting the app. + +
+ +Restores the effects of actions that were previously undone using the undo command. Format: `redo` @@ -349,12 +427,11 @@ need to save manually. ### Editing the data file -MediLink Contacts 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. +MediLink Contacts 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. However, please ensure that the edits are valid, else it may cause unexpected behaviours when the invalid data is not detected by the system.
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, MediLink Contacts 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. +If your changes to the data file makes its format invalid, MediLink Contacts may 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. Some changes may also be invalid, but not detected by the system. In that case, there may be many unexpected behaviours due to those undetected errors.
### Archiving data files `[coming in v2.0]` @@ -381,20 +458,20 @@ the data of your previous MediLink Contacts home folder. ## Command summary -| Action | Format, Examples | -|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **New Doctor** | `add-doctor n/NAME ic/IC g/GENDER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
e.g., `add-doctor n/John Doe ic/S9851386G g/M p/98765432 e/johnd@example.com a/John street, block 123, #01-01 t/Pediatrician` | +| Action | Format, Examples | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **New Doctor** | `add-doctor n/NAME ic/IC g/GENDER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
e.g., `add-doctor n/John Doe ic/S9851386G g/M p/98765432 e/johnd@example.com a/John street, block 123, #01-01 t/Pediatrician` | | **New Patient** | `add-patient n/NAME ic/IC g/GENDER p/PHONE_NUMBER ec/EMERGENCY_CONTACT e/EMAIL a/ADDRESS [t/TAG] [d/DOCTOR] [c/CONDITION] [b/BLOODTYPE] …​`
e.g., `add-patient n/Betsy Crowe ic/S9851586G g/F p/98765433 e/betsycrowe@example.com a/#104-C, Wakanda St 42 c/AIDS b/O+ t/High` | -| **New Appointment** | `new-appt pic/IC dic/IC time/yyyy-MM-dd HH:mm`
e.g., `new-appt pic/T0123456H dic/S9851586G time/2023-10-30 13:00` | -| **Delete Appointment** | `delete-appt INDEX`
e.g., delete-appt 1 | -| **Find Appointment** | `find-appt NRIC`
e.g., find-appt T00012220 | -| **Clear** | `clear` | -| **Undo** | `undo` | -| **Redo** | `redo` | +| **New Appointment** | `new-appt pic/IC dic/IC time/yyyy-MM-dd HH:mm`
e.g., `new-appt pic/T0123456H dic/S9851586G time/2023-10-30 13:00` | +| **Delete Appointment** | `delete-appt INDEX`
e.g., delete-appt 1 | +| **Find Appointment** | `find-appt NRIC`
e.g., find-appt T00012220 | +| **Clear** | `clear` | +| **Undo** | `undo` | +| **Redo** | `redo` | | **Delete** | `delete NRIC`
e.g., `delete T0666485G` | -| **Edit** | `edit NRIC [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit S9760431H n/James Lee e/jameslee@example.com` | -| **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` | -| **List** | `list` | -| **Help** | `help` | -| **Exit** | `exit` | +| **Edit** | `edit NRIC [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit S9760431H n/James Lee e/jameslee@example.com` | +| **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` | +| **List** | `list` | +| **Help** | `help` | +| **Exit** | `exit` | diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index 2a2c08675c7..fdc2a96164a 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -6,6 +6,7 @@ import seedu.address.logic.parser.Prefix; import seedu.address.model.appointment.Appointment; +import seedu.address.model.person.Patient; import seedu.address.model.person.Person; /** @@ -46,8 +47,17 @@ public static String format(Person person) { .append("; Email: ") .append(person.getEmail()) .append("; Address: ") - .append(person.getAddress()) - .append("; Tags: "); + .append(person.getAddress()); + if (person instanceof Patient) { + Patient patient = (Patient) person; + builder.append("; Emergency Contact: ") + .append(patient.getEmergencyContact()) + .append("; Blood Type: ") + .append(patient.getBloodType()) + .append("; Condition: ") + .append(patient.getCondition()); + } + builder.append("; Tags: "); person.getTags().forEach(builder::append); builder.append("; Appointments: "); person.getAppointments().forEach(builder::append); diff --git a/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java b/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java index 5bd5e0fb40c..a45f8febe58 100644 --- a/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddAppointmentCommand.java @@ -87,10 +87,6 @@ private void checkPatientAndDoctor(Patient chosenPatient, Doctor chosenDoctor) t if (chosenDoctor == null) { throw new CommandException(MESSAGE_INVALID_DOCTOR); } - // check that patient and doctor are not the same person - if (chosenPatient.isSamePerson(chosenDoctor)) { - throw new CommandException(MESSAGE_SAME_DOCTOR_AND_PATIENT); - } } private Patient findPatient(Model model) { diff --git a/src/main/java/seedu/address/logic/commands/AddDoctorCommand.java b/src/main/java/seedu/address/logic/commands/AddDoctorCommand.java index 75207d50ce5..7da87dbf757 100644 --- a/src/main/java/seedu/address/logic/commands/AddDoctorCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddDoctorCommand.java @@ -28,19 +28,19 @@ public class AddDoctorCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + "Parameters: " + PREFIX_NAME + "NAME " + + PREFIX_NRIC + "NRIC " + + PREFIX_GENDER + "GENDER " + PREFIX_PHONE + "PHONE " + PREFIX_EMAIL + "EMAIL " + PREFIX_ADDRESS + "ADDRESS " - + PREFIX_GENDER + "GENDER " - + PREFIX_NRIC + "NRIC " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "John Doe " + + PREFIX_NRIC + "S1234567Z " + + PREFIX_GENDER + "M " + PREFIX_PHONE + "98765432 " + PREFIX_EMAIL + "johnd@example.com " + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " - + PREFIX_GENDER + "M " - + PREFIX_NRIC + "S1234567Z " + PREFIX_TAG + "SURGEON"; public static final String MESSAGE_SUCCESS = "New doctor added: %1$s"; diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 643a7c793c7..9cca0d3e9e9 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -157,12 +157,6 @@ public void setDoctor(Doctor target, Doctor editedDoctor) { doctors.setObject(target, editedDoctor); } - public void setAppointment(Appointment target, Appointment editedAppointment) { - requireNonNull(editedAppointment); - - appointments.setObject(target, editedAppointment); - } - /** * Removes {@code key} from this {@code AddressBook}. * {@code key} must exist in the address book. @@ -232,6 +226,7 @@ public boolean equals(Object other) { && doctors.equals((otherAddressBook.doctors)) && appointments.equals((otherAddressBook.appointments)); } + @Override public int hashCode() { return Objects.hash(patients, doctors, appointments); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index fd4a8ff64f3..4b74023ca77 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -92,13 +92,6 @@ public interface Model { void addAppointment(Appointment appointment); - void setAppointment(Appointment target, Appointment editedAppointment); - - /** - * Returns an unmodifiable view of the filtered person list - */ - ObservableList getFilteredPersonList(); - /** * Returns an unmodifiable view of the filtered patient list */ diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index ddf7093991b..39eec66c5d3 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -133,12 +133,10 @@ public ReadOnlyAddressBook getAddressBook() { @Override public boolean hasPerson(Person person) { requireNonNull(person); - if (person instanceof Patient) { + if (person.isPatient()) { return addressBook.hasPatient((Patient) person); - } else if (person instanceof Doctor) { - return addressBook.hasDoctor((Doctor) person); } else { - return false; + return addressBook.hasDoctor((Doctor) person); } } @Override @@ -196,19 +194,6 @@ public void setPerson(Person target, Person editedPerson) { } } - @Override - public void setAppointment(Appointment target, Appointment editedAppointment) { - updateBackup(); - addressBook.setAppointment(target, editedAppointment); - } - - /** - * Returns an unmodifiable view of the filtered person list - */ - @Override - public ObservableList getFilteredPersonList() { - return null; - } //=========== Filtered Person List Accessors ============================================================= @@ -240,6 +225,7 @@ public void updateFilteredPersonList(Predicate predicate) { filteredPatients.setPredicate(predicate); filteredDoctors.setPredicate(predicate); } + @Override public void updateFilteredAppointmentList(Predicate predicate) { requireNonNull(predicate); @@ -261,7 +247,8 @@ public boolean equals(Object other) { return addressBook.equals(otherModelManager.addressBook) && userPrefs.equals(otherModelManager.userPrefs) && filteredDoctors.equals(otherModelManager.filteredDoctors) - && filteredPatients.equals(otherModelManager.filteredPatients); + && filteredPatients.equals(otherModelManager.filteredPatients) + && filteredAppointments.equals(otherModelManager.filteredAppointments); } } diff --git a/src/main/java/seedu/address/model/appointment/Appointment.java b/src/main/java/seedu/address/model/appointment/Appointment.java index b702ab733af..5b0804da74f 100644 --- a/src/main/java/seedu/address/model/appointment/Appointment.java +++ b/src/main/java/seedu/address/model/appointment/Appointment.java @@ -32,24 +32,6 @@ public Appointment(Ic doctorIc, Ic patientIc, AppointmentTime appointmentTime) { this.appointmentTime = appointmentTime; } - /** - * Constructs a new appointment with the specified doctor, patient, appointment time, and status. - * - * @param doctorIc The doctor involved in the appointment. - * @param patientIc The patient involved in the appointment. - * @param appointmentTime The date and time of the appointment. - * @param status The status of the appointment. - */ - public Appointment(Ic doctorIc, Ic patientIc, AppointmentTime appointmentTime, String status) { - requireNonNull(doctorIc); - requireNonNull(patientIc); - requireNonNull(appointmentTime); - requireNonNull(status); - this.doctorIc = doctorIc; - this.patientIc = patientIc; - this.appointmentTime = appointmentTime; - } - public AppointmentTime getAppointmentTime() { return appointmentTime; } diff --git a/src/main/java/seedu/address/model/appointment/AppointmentTime.java b/src/main/java/seedu/address/model/appointment/AppointmentTime.java index 8973acf6d71..c997fec687c 100644 --- a/src/main/java/seedu/address/model/appointment/AppointmentTime.java +++ b/src/main/java/seedu/address/model/appointment/AppointmentTime.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.time.format.ResolverStyle; /** @@ -14,8 +15,10 @@ */ public class AppointmentTime implements Comparable { - public static final String MESSAGE_CONSTRAINTS = "AppointmentTime should be in the format of yyyy-mm-dd HH:mm:ss\n"; - public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + public static final String MESSAGE_CONSTRAINTS = + "AppointmentTime should be valid date and time in the format of yyyy-mm-dd HH:mm:ss\n"; + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm") + .withResolverStyle(ResolverStyle.STRICT); public final LocalDateTime value; /** diff --git a/src/main/java/seedu/address/model/person/Ic.java b/src/main/java/seedu/address/model/person/Ic.java index 1df4b5fa569..1ae41880bf2 100644 --- a/src/main/java/seedu/address/model/person/Ic.java +++ b/src/main/java/seedu/address/model/person/Ic.java @@ -12,7 +12,7 @@ public class Ic { public static final String MESSAGE_CONSTRAINTS = "Ic should start with S or T, followed by 7 numbers, and ends with a letter. " - + "Letters must be in all caps. Empty strings are not allowed\n"; + + "Letters inputs are case-insensitive. Empty strings are not allowed\n"; public static final String VALIDATION_REGEX = "^[TS]\\d{7}[A-Z]$"; public final String value; diff --git a/src/main/java/seedu/address/model/person/Patient.java b/src/main/java/seedu/address/model/person/Patient.java index ca4a11a46c2..e2dcef75cbc 100644 --- a/src/main/java/seedu/address/model/person/Patient.java +++ b/src/main/java/seedu/address/model/person/Patient.java @@ -95,7 +95,8 @@ public boolean equals(Object other) { @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, gender, ic, condition, bloodType, appointments, tags); + return Objects.hash(name, phone, emergencyContact, email, address, gender, ic, condition, bloodType, + appointments, tags); } @Override diff --git a/src/main/java/seedu/address/storage/JsonAdaptedDoctor.java b/src/main/java/seedu/address/storage/JsonAdaptedDoctor.java index 67a7f34c018..4b9ad0b9db3 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedDoctor.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedDoctor.java @@ -21,7 +21,6 @@ import seedu.address.model.tag.Tag; - /** * Jackson-friendly version of {@link Doctor}. */ @@ -66,10 +65,7 @@ public Doctor toModelType() throws IllegalValueException { personTags.add(tag.toModelDoctorType()); } final Set modelTags = new HashSet<>(personTags); - final List personAppointments = new ArrayList<>(); - for (JsonAdaptedAppointment appointment : this.getAppointments()) { - personAppointments.add(appointment.toModelType()); - } + final List personAppointments = checkAppointments(); final Set modelAppointments = new HashSet<>(personAppointments); return new Doctor(modelName, modelPhone, modelEmail, modelAddress, modelRemark, modelGender, modelIc, modelAppointments, modelTags); diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPatient.java b/src/main/java/seedu/address/storage/JsonAdaptedPatient.java index e57cec044ee..b8d3739ff45 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPatient.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPatient.java @@ -81,10 +81,7 @@ public Patient toModelType() throws IllegalValueException { final Set modelTags = new HashSet<>(personTags); final Condition modelCondition = checkCondition(); final BloodType modelBloodType = checkBloodType(); - final List personAppointments = new ArrayList<>(); - for (JsonAdaptedAppointment appointment : this.getAppointments()) { - personAppointments.add(appointment.toModelType()); - } + final List personAppointments = checkAppointments(); final Set modelAppointments = new HashSet<>(personAppointments); return new Patient(modelName, modelPhone, modelEmergencyContact, modelEmail, modelAddress, modelRemark, modelGender, modelIc, modelCondition, modelBloodType, modelAppointments, modelTags); diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java index bcd97932c7e..2756b3d1969 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java @@ -25,6 +25,10 @@ public abstract class JsonAdaptedPerson { public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!"; + public static final String MESSAGE_DUPLICATE_APPOINTMENT_TIME = + "Person has more than 1 appointment at the same timing!"; + public static final String MESSAGE_INVALID_APPOINTMENT = + "Person contains an appointment that does not belong to him!"; private final String name; private final String phone; @@ -92,6 +96,7 @@ public List getTags() { public List getAppointments() { return this.appointments; } + /** * Checks the name given by storage. * @@ -203,6 +208,8 @@ public Ic checkIc() throws IllegalValueException { /** * Gives the list of appointments of the Person. + * Please ensure that this method is called only after the Ic has been added to the person. + * This checks for any appointments happening at the same time and any appointments not belonging to this person. * * @return a List of JsonAdaptedAppointments */ diff --git a/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java b/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java index 22abe38fb05..e1a0ddd9e77 100644 --- a/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddAppointmentCommandTest.java @@ -158,19 +158,6 @@ public void addAppointment(Appointment appointment) { throw new AssertionError("This method should not be called."); } - @Override - public void setAppointment(Appointment target, Appointment editedAppointment) { - throw new AssertionError("This method should not be called."); - } - - /** - * Returns an unmodifiable view of the filtered person list - */ - @Override - public ObservableList getFilteredPersonList() { - return null; // not sure abt this method - } - @Override public ObservableList getFilteredPatientList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/AddAppointmentIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddAppointmentIntegrationTest.java index 8b93d2d2f0f..fde2e2cac58 100644 --- a/src/test/java/seedu/address/logic/commands/AddAppointmentIntegrationTest.java +++ b/src/test/java/seedu/address/logic/commands/AddAppointmentIntegrationTest.java @@ -4,7 +4,9 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalAddressBook.getTypicalAddressBook; +import static seedu.address.testutil.TypicalDoctor.CHERYL; import static seedu.address.testutil.TypicalDoctor.DEREK; +import static seedu.address.testutil.TypicalPatient.AMY; import static seedu.address.testutil.TypicalPatient.BOB; import java.util.Set; @@ -18,7 +20,6 @@ import seedu.address.model.appointment.Appointment; import seedu.address.model.person.Doctor; import seedu.address.model.person.Patient; -import seedu.address.model.person.Person; import seedu.address.testutil.AppointmentBuilder; import seedu.address.testutil.DoctorBuilder; import seedu.address.testutil.PatientBuilder; @@ -45,23 +46,117 @@ public void execute_newAppointment_success() { new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - //expectedModel.addAppointment(validAppointment); + expectedModel.addAppointment(validAppointment); assertCommandSuccess(new AddAppointmentCommand(validAppointment), model, String.format(AddAppointmentCommand.MESSAGE_SUCCESS, validAppointment), expectedModel); + // check that the appointments have been added to all patients, doctors and appointment list Set patientAppointments = bob.getAppointments(); Set doctorAppointments = derek.getAppointments(); assertTrue(patientAppointments.contains(validAppointment)); assertTrue(doctorAppointments.contains(validAppointment)); + assertTrue(model.getFilteredAppointmentList().contains(validAppointment)); } @Test - public void execute_duplicatePerson_throwsCommandException() { - Person personInList = model.getAddressBook().getPatientList().get(0); - assertCommandFailure(new AddCommand(personInList), model, - AddCommand.MESSAGE_DUPLICATE_PERSON); + public void execute_appointmentWithPatientNotInModel_throwsCommandException() { + Doctor derek = new DoctorBuilder(DEREK).build(); + Patient bob = new PatientBuilder(BOB).build(); + // only add doctor + model.addPerson(derek); + Appointment invalidAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); + + assertCommandFailure(new AddAppointmentCommand(invalidAppointment), model, + AddAppointmentCommand.MESSAGE_INVALID_PATIENT); + } + + @Test + public void execute_appointmentWithDoctorNotInModel_throwsCommandException() { + Doctor derek = new DoctorBuilder(DEREK).build(); + Patient bob = new PatientBuilder(BOB).build(); + // only add patient + model.addPerson(bob); + Appointment invalidAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); + + assertCommandFailure(new AddAppointmentCommand(invalidAppointment), model, + AddAppointmentCommand.MESSAGE_INVALID_DOCTOR); + } + + @Test + public void execute_appointmentWithDoctorHasAppointmentAtTheSameTime_throwsCommandException() { + Doctor derek = new DoctorBuilder(DEREK).build(); + Patient bob = new PatientBuilder(BOB).build(); + model.addPerson(derek); + model.addPerson(bob); + Appointment validAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.addAppointment(validAppointment); + + assertCommandSuccess(new AddAppointmentCommand(validAppointment), model, + String.format(AddAppointmentCommand.MESSAGE_SUCCESS, validAppointment), + expectedModel); + + Patient amy = new PatientBuilder(AMY).build(); + model.addPerson(amy); + // create another appointment between Amy and Doctor Derek at the same time + Appointment invalidAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(amy.getIc()).build(); + + assertCommandFailure(new AddAppointmentCommand(invalidAppointment), model, + AddAppointmentCommand.MESSAGE_DUPLICATE_APPOINTMENT_DOCTOR); + } + + @Test + public void execute_appointmentWithPatientHasAppointmentAtTheSameTime_throwsCommandException() { + Doctor derek = new DoctorBuilder(DEREK).build(); + Patient bob = new PatientBuilder(BOB).build(); + model.addPerson(derek); + model.addPerson(bob); + Appointment validAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.addAppointment(validAppointment); + + assertCommandSuccess(new AddAppointmentCommand(validAppointment), model, + String.format(AddAppointmentCommand.MESSAGE_SUCCESS, validAppointment), + expectedModel); + + Doctor cheryl = new DoctorBuilder(CHERYL).build(); + model.addPerson(cheryl); + // create another appointment between patient Bob and Doctor cheryl at the same time + Appointment invalidAppointment = + new AppointmentBuilder().withDoctorIc(cheryl.getIc()).withPatientIc(bob.getIc()).build(); + + assertCommandFailure(new AddAppointmentCommand(invalidAppointment), model, + AddAppointmentCommand.MESSAGE_DUPLICATE_APPOINTMENT_PATIENT); + } + + @Test + public void execute_duplicateAppointment_throwsCommandException() { + Doctor derek = new DoctorBuilder(DEREK).build(); + Patient bob = new PatientBuilder(BOB).build(); + model.addPerson(derek); + model.addPerson(bob); + Appointment validAppointment = + new AppointmentBuilder().withDoctorIc(derek.getIc()).withPatientIc(bob.getIc()).build(); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.addAppointment(validAppointment); + + assertCommandSuccess(new AddAppointmentCommand(validAppointment), model, + String.format(AddAppointmentCommand.MESSAGE_SUCCESS, validAppointment), + expectedModel); + + // try to add the same appointment again will give an error + assertCommandFailure(new AddAppointmentCommand(validAppointment), model, + AddAppointmentCommand.MESSAGE_DUPLICATE_APPOINTMENT_PATIENT); } } diff --git a/src/test/java/seedu/address/logic/commands/AddDoctorCommandTest.java b/src/test/java/seedu/address/logic/commands/AddDoctorCommandTest.java index fbc6d683f96..5a9db45c360 100644 --- a/src/test/java/seedu/address/logic/commands/AddDoctorCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddDoctorCommandTest.java @@ -33,7 +33,7 @@ public class AddDoctorCommandTest { @Test public void constructor_nullDoctor_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new AddCommand(null)); + assertThrows(NullPointerException.class, () -> new AddDoctorCommand(null)); } @@ -42,9 +42,9 @@ public void execute_doctorAcceptedByModel_addSuccessful() throws Exception { ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded(); Doctor validDoctor = new DoctorBuilder().build(); - CommandResult commandResult = new AddCommand(validDoctor).execute(modelStub); + CommandResult commandResult = new AddDoctorCommand(validDoctor).execute(modelStub); - assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.format(validDoctor)), + assertEquals(String.format(AddDoctorCommand.MESSAGE_SUCCESS, Messages.format(validDoctor)), commandResult.getFeedbackToUser()); assertEquals(Arrays.asList(validDoctor), modelStub.personsAdded); } @@ -52,10 +52,11 @@ public void execute_doctorAcceptedByModel_addSuccessful() throws Exception { @Test public void execute_duplicateDoctor_throwsCommandException() { Doctor validDoctor = new DoctorBuilder().build(); - AddDoctorCommand addCommand = new AddDoctorCommand(validDoctor); + AddDoctorCommand addDoctorCommand = new AddDoctorCommand(validDoctor); ModelStub modelStub = new ModelStubWithDoctor(validDoctor); - assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub)); + assertThrows(CommandException.class, AddDoctorCommand.MESSAGE_DUPLICATE_PERSON, () -> + addDoctorCommand.execute(modelStub)); } @Test @@ -84,9 +85,9 @@ public void equals() { @Test public void toStringMethod() { - AddDoctorCommand addCommand = new AddDoctorCommand(WAYNE); + AddDoctorCommand addDoctorCommand = new AddDoctorCommand(WAYNE); String expected = AddDoctorCommand.class.getCanonicalName() + "{toAdd=" + WAYNE + "}"; - assertEquals(expected, addCommand.toString()); + assertEquals(expected, addDoctorCommand.toString()); } /** @@ -148,7 +149,6 @@ public ReadOnlyAddressBook getAddressBook() { 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."); @@ -164,19 +164,6 @@ public void addAppointment(Appointment appointment) { throw new AssertionError("This method should not be called."); } - @Override - public void setAppointment(Appointment target, Appointment editedAppointment) { - throw new AssertionError("This method should not be called."); - } - - /** - * Returns an unmodifiable view of the filtered person list - */ - @Override - public ObservableList getFilteredPersonList() { - return null; // not sure abt this method - } - @Override public ObservableList getFilteredPatientList() { throw new AssertionError("This method should not be called."); @@ -265,6 +252,10 @@ public void addPerson(Person person) { public ReadOnlyAddressBook getAddressBook() { return new AddressBook(); } + @Override + public boolean hasIc(Ic nric) { + return personsAdded.stream().anyMatch(person -> person.getIc().equals(nric)); + } } } diff --git a/src/test/java/seedu/address/logic/commands/AddPatientCommandTest.java b/src/test/java/seedu/address/logic/commands/AddPatientCommandTest.java index 99476de0dca..2c8ec690dd3 100644 --- a/src/test/java/seedu/address/logic/commands/AddPatientCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddPatientCommandTest.java @@ -167,19 +167,6 @@ public void addAppointment(Appointment appointment) { throw new AssertionError("This method should not be called."); } - @Override - public void setAppointment(Appointment target, Appointment editedAppointment) { - throw new AssertionError("This method should not be called."); - } - - /** - * Returns an unmodifiable view of the filtered person list - */ - @Override - public ObservableList getFilteredPersonList() { - return null; // not sure abt this method - } - @Override public ObservableList getFilteredPatientList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 1df2dc5704d..fc37303c9ec 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -9,6 +9,8 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.AddAppointmentCommand; +import seedu.address.logic.commands.AddDoctorCommand; import seedu.address.logic.commands.AddPatientCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.DeleteAppointmentCommand; @@ -19,8 +21,16 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.RedoCommand; +import seedu.address.logic.commands.UndoCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.appointment.Appointment; +import seedu.address.model.person.Doctor; import seedu.address.model.person.Patient; +import seedu.address.testutil.AppointmentBuilder; +import seedu.address.testutil.AppointmentUtil; +import seedu.address.testutil.DoctorBuilder; +import seedu.address.testutil.DoctorUtil; import seedu.address.testutil.EditPersonDescriptorBuilder; import seedu.address.testutil.PatientBuilder; import seedu.address.testutil.PatientUtil; @@ -37,6 +47,13 @@ public void parseCommand_add_patient() throws Exception { assertEquals(new AddPatientCommand(patient), command); } + @Test + public void parseCommand_add_doctor() throws Exception { + Doctor doctor = new DoctorBuilder().build(); + AddDoctorCommand command = (AddDoctorCommand) parser.parseCommand(DoctorUtil.getAddDoctorCommand(doctor)); + assertEquals(new AddDoctorCommand(doctor), command); + } + @Test public void parseCommand_clear() throws Exception { assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand); @@ -50,6 +67,14 @@ public void parseCommand_delete() throws Exception { assertEquals(new DeleteCommand(FIRST_NRIC), command); } + @Test + public void parseCommand_addAppointment() throws Exception { + Appointment appointment = new AppointmentBuilder().build(); + AddAppointmentCommand command = + (AddAppointmentCommand) parser.parseCommand(AppointmentUtil.getAddAppointmentCommand(appointment)); + assertEquals(new AddAppointmentCommand(appointment), command); + } + @Test public void parseCommand_deleteAppointment() throws Exception { DeleteAppointmentCommand command = (DeleteAppointmentCommand) parser.parseCommand( @@ -66,6 +91,18 @@ public void parseCommand_edit() throws Exception { assertEquals(new EditCommand(person.getIc(), descriptor), command); } + @Test + public void parseCommand_undo() throws Exception { + assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand); + assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD + " 3") instanceof UndoCommand); + } + + @Test + public void parseCommand_redo() throws Exception { + assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand); + assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD + " 3") instanceof RedoCommand); + } + @Test public void parseCommand_exit() throws Exception { assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand); diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index c892b2a76ea..5e6e6be3fef 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -16,6 +16,7 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.Ic; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -25,6 +26,8 @@ public class ParserUtilTest { 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_IC1 = "Y9834876G"; + private static final String INVALID_IC2 = "T934865H"; private static final String INVALID_PATIENT_TAG = "priority: HIGHEST"; private static final String INVALID_DOCTOR_TAG1 = "NURSE"; @@ -32,6 +35,8 @@ public class ParserUtilTest { 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_IC1 = "T1234567H"; + private static final String VALID_IC2 = "t1234567h"; private static final String VALID_TAG1 = "FRIENDS"; private static final String VALID_TAG2 = "STUDENT"; private static final String VALID_PATIENT_TAG1 = "priority: LOW"; @@ -153,6 +158,34 @@ public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exc assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace)); } + @Test + public void parseIc_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> ParserUtil.parseIc((String) null)); + } + + @Test + public void parseIc_invalidStartingCharacter_throwsParseException() { + assertThrows(ParseException.class, () -> ParserUtil.parseIc(INVALID_IC1)); + } + + @Test + public void parseIc_invalidNumbers_throwsParseException() { + assertThrows(ParseException.class, () -> ParserUtil.parseIc(INVALID_IC2)); + } + + @Test + public void parseIc_validIcWithCaps_returnsIc() throws Exception { + Ic expectedIc = new Ic(VALID_IC1); + assertEquals(expectedIc, ParserUtil.parseIc(VALID_IC1)); + } + + @Test + public void parseIc_validIcWithoutCaps_returnsIc() throws Exception { + String inputIc = VALID_IC2.toUpperCase(); + Ic expectedIc = new Ic(inputIc); + assertEquals(expectedIc, ParserUtil.parseIc(VALID_IC2)); + } + @Test public void parseTag_null_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null)); diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index 165fb4b4955..d5ea397d03a 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -7,6 +7,7 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_LOW; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalAddressBook.getTypicalAddressBook; +import static seedu.address.testutil.TypicalAppointment.APPOINTMENT_1; import static seedu.address.testutil.TypicalPatient.ALICE; import java.util.Arrays; @@ -23,6 +24,7 @@ import seedu.address.model.person.Patient; import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.DuplicatePersonException; +import seedu.address.testutil.AppointmentBuilder; import seedu.address.testutil.PatientBuilder; public class AddressBookTest { @@ -81,6 +83,29 @@ public void hasPatient_patientWithSameIdentityFieldsInAddressBook_returnsTrue() assertTrue(addressBook.hasPatient(editedAlice)); } + @Test + public void hasAppointment_nullAppointment_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> addressBook.hasAppointment(null)); + } + + @Test + public void hasAppointment_appointmentNotInAddressBook_returnsFalse() { + assertFalse(addressBook.hasAppointment(APPOINTMENT_1)); + } + + @Test + public void hasAppointment_appointmentInAddressBook_returnsTrue() { + addressBook.addAppointment(APPOINTMENT_1); + assertTrue(addressBook.hasAppointment(APPOINTMENT_1)); + } + + @Test + public void hasAppointment_appointmentWithSameFieldsInAddressBook_returnsTrue() { + addressBook.addAppointment(APPOINTMENT_1); + Appointment appointment = new AppointmentBuilder().build(); + assertTrue(addressBook.hasAppointment(appointment)); + } + @Test public void getPatientList_modifyList_throwsUnsupportedOperationException() { assertThrows(UnsupportedOperationException.class, () -> addressBook.getPatientList().remove(0)); diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 030b71070aa..a23a63013b2 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalDoctor.BOYD; import static seedu.address.testutil.TypicalPatient.ALICE; import static seedu.address.testutil.TypicalPatient.BENSON; @@ -79,12 +80,15 @@ public void hasPerson_nullPerson_throwsNullPointerException() { @Test public void hasPerson_personNotInAddressBook_returnsFalse() { assertFalse(modelManager.hasPerson(ALICE)); + assertFalse(modelManager.hasPerson(BOYD)); } @Test public void hasPerson_personInAddressBook_returnsTrue() { modelManager.addPerson(ALICE); assertTrue(modelManager.hasPerson(ALICE)); + modelManager.addPerson(BOYD); + assertTrue(modelManager.hasPerson(BOYD)); } @Test diff --git a/src/test/java/seedu/address/model/person/AppointmentTest.java b/src/test/java/seedu/address/model/person/AppointmentTest.java index 7b4a67dbfc0..ab0856164cf 100644 --- a/src/test/java/seedu/address/model/person/AppointmentTest.java +++ b/src/test/java/seedu/address/model/person/AppointmentTest.java @@ -43,25 +43,18 @@ public void constructor_nullAppointmentTime_throwsNullPointerException() { @Test public void secondConstructor_nullDoctor_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> new Appointment(null, new Ic(VALID_NRIC_AMY), - new AppointmentTime(VALID_DATE_1), "Follow-Up")); + new AppointmentTime(VALID_DATE_1))); } @Test public void secondConstructorr_nullPatient_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> new Appointment(new Ic(VALID_NRIC_DEREK), null, - new AppointmentTime(VALID_DATE_1), "Follow-Up")); + new AppointmentTime(VALID_DATE_1))); } @Test public void secondConstructor_nullAppointmentTime_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> new Appointment(new Ic(VALID_NRIC_DEREK), new Ic(VALID_NRIC_AMY), - null, "Follow-Up")); - } - - @Test - public void constructor_nullStatus() { // should this throw a nullPointerException? - assertThrows(NullPointerException.class, ( - ) -> new Appointment(new Ic(VALID_NRIC_DEREK), new Ic(VALID_NRIC_AMY), new AppointmentTime(VALID_DATE_1), null)); } diff --git a/src/test/java/seedu/address/model/person/IcTest.java b/src/test/java/seedu/address/model/person/IcTest.java index eb3c4ec5de4..bb24fcdea6f 100644 --- a/src/test/java/seedu/address/model/person/IcTest.java +++ b/src/test/java/seedu/address/model/person/IcTest.java @@ -34,6 +34,7 @@ public void isValidIc() { assertFalse(Ic.isValidIc(" ")); // spaces only assertFalse(Ic.isValidIc("S333444Z")); // only 6 numbers included assertFalse(Ic.isValidIc("G2223331H")); // starting alphabet not S or T + assertFalse(Ic.isValidIc("s2223331H")); // alphabets not in caps // valid nric assertTrue(Ic.isValidIc("S0345999H")); // starting alphabet S diff --git a/src/test/java/seedu/address/model/person/PatientTest.java b/src/test/java/seedu/address/model/person/PatientTest.java index ed27896278a..415fba681d9 100644 --- a/src/test/java/seedu/address/model/person/PatientTest.java +++ b/src/test/java/seedu/address/model/person/PatientTest.java @@ -49,6 +49,11 @@ public void isSamePerson() { assertFalse(ALICE.isSamePerson(editedAlice)); } + @Test + public void isDoctor() { + assertFalse(ALICE.isDoctor()); + } + @Test public void equals() { // same values -> returns true @@ -100,6 +105,51 @@ public void equals() { assertFalse(ALICE.equals(editedAlice)); } + @Test + public void hashCodeTest() { + // same values -> returns true + Patient aliceCopy = new PatientBuilder(ALICE).build(); + assertTrue(ALICE.hashCode() == aliceCopy.hashCode()); + + // same object -> returns true + assertTrue(ALICE.hashCode() == ALICE.hashCode()); + + // different person shuold have different hashCode -> returns false + assertFalse(ALICE.hashCode() == BOB.hashCode()); + + // different name -> returns false + Patient editedAlice = new PatientBuilder(ALICE).withName(VALID_NAME_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different phone -> returns false + editedAlice = new PatientBuilder(ALICE).withPhone(VALID_PHONE_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different email -> returns false + editedAlice = new PatientBuilder(ALICE).withEmail(VALID_EMAIL_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different address -> returns false + editedAlice = new PatientBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different tags -> returns false + editedAlice = new PatientBuilder(ALICE).withTags(VALID_TAG_MEDIUM).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different emergency contact -> return false + editedAlice = new PatientBuilder(ALICE).withEmergencyContact(VALID_EMERGENCY_CONTACT_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different condition -> return false + editedAlice = new PatientBuilder(ALICE).withCondition(VALID_CONDITION_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + + // different blood type -> return false + editedAlice = new PatientBuilder(ALICE).withBloodType(VALID_BLOODTYPE_BOB).build(); + assertFalse(ALICE.hashCode() == editedAlice.hashCode()); + } + @Test public void toStringMethod() { String expected = Patient.class.getCanonicalName() + "{name=" + ALICE.getName() + ", phone=" + ALICE.getPhone() diff --git a/src/test/java/seedu/address/storage/JsonAdaptedAppointmentTest.java b/src/test/java/seedu/address/storage/JsonAdaptedAppointmentTest.java new file mode 100644 index 00000000000..249a33e4da1 --- /dev/null +++ b/src/test/java/seedu/address/storage/JsonAdaptedAppointmentTest.java @@ -0,0 +1,94 @@ +package seedu.address.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalAppointment.APPOINTMENT_1; +import static seedu.address.testutil.TypicalPatient.BENSON; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.appointment.AppointmentTime; +import seedu.address.model.person.Ic; + +public class JsonAdaptedAppointmentTest { + + private static final String INVALID_IC = "A1234567G"; + private static final String INVALID_PATIENT_IC = "S123Z"; + private static final String INVALID_APPOINTMENT_TIME = "123456"; + + private static final String VALID_DOCTOR_IC = APPOINTMENT_1.getDoctor().toString(); + private static final String VALID_PATIENT_IC = APPOINTMENT_1.getPatient().toString(); + private static final String VALID_APPOINTMENT_TIME = APPOINTMENT_1.getAppointmentTime().toString(); + + @Test + public void toModelType_validPatientDetails_returnsPatient() throws Exception { + JsonAdaptedPatient patient = new JsonAdaptedPatient(BENSON); + assertEquals(BENSON, patient.toModelType()); + } + + @Test + public void toModelType_invalidPatientIc_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(VALID_DOCTOR_IC, INVALID_IC, VALID_APPOINTMENT_TIME); + String expectedMessage = Ic.MESSAGE_CONSTRAINTS; + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_nullPatientIc_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(VALID_DOCTOR_IC, null, VALID_APPOINTMENT_TIME); + String expectedMessage = + String.format(JsonAdaptedAppointment.MISSING_FIELD_MESSAGE_FORMAT, Ic.class.getSimpleName()); + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_invalidDoctorIc_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(INVALID_IC, VALID_PATIENT_IC, VALID_APPOINTMENT_TIME); + String expectedMessage = Ic.MESSAGE_CONSTRAINTS; + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_nullDoctorIc_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(null, VALID_PATIENT_IC, VALID_APPOINTMENT_TIME); + String expectedMessage = + String.format(JsonAdaptedAppointment.MISSING_FIELD_MESSAGE_FORMAT, Ic.class.getSimpleName()); + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_invalidAppointment_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(VALID_DOCTOR_IC, VALID_PATIENT_IC, INVALID_APPOINTMENT_TIME); + String expectedMessage = AppointmentTime.MESSAGE_CONSTRAINTS; + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_nullAppointment_throwsIllegalValueException() { + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(VALID_DOCTOR_IC, VALID_PATIENT_IC, null); + String expectedMessage = String.format(JsonAdaptedAppointment.MISSING_FIELD_MESSAGE_FORMAT, + AppointmentTime.class.getSimpleName()); + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + + @Test + public void toModelType_duplicateIc_throwsIllegalValueException() { + // same patient ic + JsonAdaptedAppointment appointment = + new JsonAdaptedAppointment(VALID_PATIENT_IC, VALID_PATIENT_IC, VALID_APPOINTMENT_TIME); + String expectedMessage = JsonAdaptedAppointment.DUPLICATE_PATIENT_AND_DOCTOR_IC; + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + // same doctor ic + appointment = + new JsonAdaptedAppointment(VALID_DOCTOR_IC, VALID_DOCTOR_IC, VALID_APPOINTMENT_TIME); + assertThrows(IllegalValueException.class, expectedMessage, appointment::toModelType); + } + +} diff --git a/src/test/java/seedu/address/storage/JsonAdaptedDoctorTest.java b/src/test/java/seedu/address/storage/JsonAdaptedDoctorTest.java index 0a8809d2cb5..d73ffe3573a 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedDoctorTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedDoctorTest.java @@ -6,18 +6,21 @@ import static seedu.address.testutil.TypicalDoctor.BOYD; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.appointment.Appointment; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Gender; import seedu.address.model.person.Ic; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; +import seedu.address.testutil.AppointmentBuilder; public class JsonAdaptedDoctorTest { private static final String INVALID_NAME = "R@chel"; @@ -36,10 +39,12 @@ public class JsonAdaptedDoctorTest { private static final String VALID_REMARK = BOYD.getRemark().toString(); private static final String VALID_GENDER = BOYD.getGender().toString(); private static final String VALID_NRIC = BOYD.getIc().toString(); + private static final Appointment BOYD_APPOINTMENT = + new AppointmentBuilder().withPatientIc(BOYD.getIc()).build(); private static final List VALID_TAGS = BOYD.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList()); - private static final List VALID_APPOINTMENTS = BOYD.getAppointments().stream() + private static final List VALID_APPOINTMENTS = Arrays.asList(BOYD_APPOINTMENT).stream() .map(JsonAdaptedAppointment::new) .collect(Collectors.toList()); diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPatientTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPatientTest.java index b901a03c03d..bf53b658f57 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedPatientTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedPatientTest.java @@ -6,12 +6,14 @@ import static seedu.address.testutil.TypicalPatient.BENSON; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.appointment.Appointment; import seedu.address.model.person.Address; import seedu.address.model.person.BloodType; import seedu.address.model.person.Condition; @@ -20,6 +22,8 @@ import seedu.address.model.person.Ic; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; +import seedu.address.model.person.Remark; +import seedu.address.testutil.AppointmentBuilder; public class JsonAdaptedPatientTest { private static final String INVALID_NAME = "R@chel"; @@ -44,10 +48,12 @@ public class JsonAdaptedPatientTest { private static final String VALID_EMERGENCY_CONTACT = BENSON.getEmergencyContact().toString(); private static final String VALID_CONDITION = BENSON.getCondition().toString(); private static final String VALID_BLOODTYPE = BENSON.getBloodType().toString(); + private static final Appointment BENSON_APPOINTMENT = + new AppointmentBuilder().withPatientIc(BENSON.getIc()).build(); private static final List VALID_TAGS = BENSON.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList()); - private static final List VALID_APPOINTMENTS = BENSON.getAppointments().stream() + private static final List VALID_APPOINTMENTS = Arrays.asList(BENSON_APPOINTMENT).stream() .map(JsonAdaptedAppointment::new) .collect(Collectors.toList()); @@ -194,6 +200,17 @@ public void toModelType_invalidTags_throwsIllegalValueException() { assertThrows(IllegalValueException.class, patient::toModelType); } + @Test + public void toModelType_nullRemark_throwsIllegalValueException() { + JsonAdaptedPatient patient = + new JsonAdaptedPatient(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, null, + VALID_GENDER, VALID_NRIC, VALID_TAGS, VALID_APPOINTMENTS, VALID_CONDITION, VALID_BLOODTYPE, + VALID_EMERGENCY_CONTACT); + String expectedMessage = + String.format(JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT, Remark.class.getSimpleName()); + assertThrows(IllegalValueException.class, expectedMessage, patient::toModelType); + } + @Test public void toModelType_invalidCondition_throwsIllegalValueException() { JsonAdaptedPatient patient = @@ -254,4 +271,12 @@ public void toModelType_nullEmergencyContact_throwsIllegalValueException() { assertThrows(IllegalValueException.class, expectedMessage, patient::toModelType); } + @Test + public void test_getAppointment() { + JsonAdaptedPatient patient = + new JsonAdaptedPatient(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_REMARK, + VALID_GENDER, VALID_NRIC, VALID_TAGS, VALID_APPOINTMENTS, VALID_CONDITION, VALID_BLOODTYPE, + VALID_EMERGENCY_CONTACT); + assertEquals(VALID_APPOINTMENTS, patient.getAppointments()); + } } diff --git a/src/test/java/seedu/address/testutil/AppointmentUtil.java b/src/test/java/seedu/address/testutil/AppointmentUtil.java new file mode 100644 index 00000000000..181020bc81e --- /dev/null +++ b/src/test/java/seedu/address/testutil/AppointmentUtil.java @@ -0,0 +1,33 @@ +package seedu.address.testutil; + +import static seedu.address.logic.parser.CliSyntax.PREFIX_APPOINTMENT_TIME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DOCTOR_IC; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PATIENT_IC; + +import seedu.address.logic.commands.AddAppointmentCommand; +import seedu.address.model.appointment.Appointment; + +/** + * A utility class for Appointment. + */ +public class AppointmentUtil { + + /** + * Returns an new-appt command string for adding the {@code appointment}. + */ + public static String getAddAppointmentCommand(Appointment appointment) { + return AddAppointmentCommand.COMMAND_WORD + " " + getAppointmentDetails(appointment); + } + + /** + * Returns the part of command string for the given {@code patient}'s details. + */ + public static String getAppointmentDetails(Appointment appointment) { + StringBuilder sb = new StringBuilder(); + sb.append(PREFIX_DOCTOR_IC + appointment.getDoctor().value + " "); + sb.append(PREFIX_PATIENT_IC + appointment.getPatient().value + " "); + sb.append(PREFIX_APPOINTMENT_TIME + appointment.getAppointmentTime().toString() + " "); + return sb.toString(); + } +} +