GitHub - https://github.com/nate-0hz/T1A3-CRM
Youtube - https://www.youtube.com/watch?v=VZF4nuslFag
Python pep8 is the style guide used. Particular attention has been paid to:
Appropriate indentation for 4 spaces Maximum line length of 79 spaces Breaking appropriately around binary operators Blank lines areound classes and elsewhere Importing on separate lines The appropriate use of whitespace in expressions and statements
The application is the beginnings of a Contact Relationship Manager (CRM), and holds basic information about the contacts held within, including:
- First and last name
- Phone number
- Company
- Email address
- Contact’s birthday
- Date the person was last contacted (manually updatable by the user)
- Date the user wishes to contact the person next (manually updatable)
The application has several features:
- Main menu
- Automatic creation of the storage csv, if it does not exist
- View Records flow
- Ability to sort and display records, by attribute
- Ability to search records for partial strings and numbers
- Ability to filter out duplicate returns, when searching
- Add Records flow
- Ability to exit the adding of a record
- An in-built check if the entered name already exists, giving the user the choice of adding the record or skipping
- Saving the added record to the storage csv file
- Edit Record flow
- Ability to search for and select the record to be edited
- Ability to update or skip updating individual fields within the record
- Contextual help from text files on several menus
The application has a main menu, which is presented when the application is launched.
The Main Menu holds selectable options to initiate the chosen flows, ability to display a simple contextual help text file, and the ability to quit the application gracefully.
On launching the application, a check is performed to determine if the storage csv file exists. If it does not, the file is automatically created, preventing any issues saving new records the user creates.
This also makes it possible to ship the application with sample data, as the user can try using the application with sample data, then delete it, prior to building their own database of records.
It does this through a try/except block for FileNotFoundError. If cram_storage.csv is not found in the /data_files folder, a csv of the same name is created, with full column headers but no data.
This feature allows the user to choose between viewing all stored records, sorted by attribute, selectable by the user, or to search for specific records.
Viewing all records uses Pandas to create a data frame from the storage csv file, the sorts the data frame in ascending order, on the column of the user’s choosing.
On selecting View All Records, the user is presented with a menu of sort by options to choose from.
Selecting from these options will display the entire database, in ascending order, on the attribute chosen.
On pressing enter, the user will return to the View Contacts Menu
Searching for records using a substring is a little more complicated. This also uses pandas to create a data frame. The substring is changed to accommodate multiple capitalisation variations, and is tested against each value in each row of the data frame, and if a match is found, the entire row is copied to temporary storage in a second csv file. Once all rows of the data frame have been searched for the substring, the application then examines the second csv for duplicate rows, and drops them, as it writes the rows to a third csv file.
When complete, the cleansed data is moved from the third csv file into a new data frame and displayed for the user.
Once the search flow is initiated, the temporary storage csv has any data it might be holding deleted, and the column headers are returned to the empty file.
As the search string can be very generic, duplicate entries are often found, where the same pattern for letters or numbers can be found in the same record:
This application handles this by dropping duplicate rows as it moves the files to the third “clean” csv file
These results are moved to a data frame through Pandas, and displayed to the user, in the same order they can be found in the main storage csv.
Adding a contact triggers the input prompt asking the user to enter the first name of the person they wish to add. At this point, the user can type “exit” to go back to the main menu.
The application then asks for the person’s last name, then performs a check whether the first and last names entered already exist in the main storage csv. If they do, the user is given the option to continue or not. Not continuing returns the user to the main menu.
If the user elects to continue, they can keep entering details until all fields have been completed. The user can press enter to leave a field blank.
On completion, the user is returned to the beginning of the add loop where they can add another user or type “exit” to exit. Continuing straight on, without giving the user an option to continue or end is faster and more convenient if adding multiple entries.
On editing a record, the user is presented with an input prompt, to enter a substring to search for.
On pressing enter, much of the view search functionality is performed here, with the substring being searched for in a data frame of all entries, and matched entries being cleansed of duplicates, then presented to the user for selection.
The user is then asked to input which record they would like to edit, be selecting the index number on the table’s left.
When selected, that row is converted to a list (chosen_record), containing the current values, and a dictionary (editing_dict) containing the current keys and values, along with an empty list (temp_list).
The dictionary is used to guide the user to make the changes, one at a time, stepping out the key and value, and giving the user the option to press ‘enter’ to keep the current value.
This process also sets and increments the index number for temp_list. If the user selects to keep the value of the key the same, the application adds the value from chosen_record to temp_list in the correct index position. If the user provides a new value, the new value is written to temp_list in the correct position index.
Once all values have been iterated through, the application finds the original row in the data frame and overwrites it with chosen_record. The user is then returned to the main menu.
Contextual help can be accessed by pressing 9 from relevant menus. A simple class has been created for help, and instances of the class have been created to display the relevant help file in the terminal.
The implementation plan was to design the flow, illustrated in the previous section, the implement the build, one section at a time, starting with the main menu.
I then planned to build the Add flow, View flow, Edit flow and Help flows as stand-alone applications that would then be called off the main menu.
As development progressed, and DRY was applied, it became clear that some functions and variables should be held in a separate file, so that they could be called upon by different flows. Relocating some functions and variables to the shared_variables.py file also improved readability of each flow.
To set out the implementation plan and track its progress, I used ClickUp, and rather than a checklist, I used subtasks. This also helped me remember to complete things I thought of when working on other tasks.
Sadly, I do not have images during development as one of the tasks I forgot to add was to take images during development, to demonstrate the use of the software during the project.
Save the repository file to your hard drive.
In a terminal window, navigate to the save location folder.
Type sh run.sh
All depedencies should be installed by the run.sh
shell script.
For clarity, the following dependency was required to be installed by the developer, for the application to run correctly:
- Pandas
The application was tested on an M2 MacBook Pro with 16 GB shared memory and 1 TB hard drive, running MacOS Ventura 13.3.1 (a). The Python version used was Python 3.11.3. You may have issues running it on an older verion of Python 3.
Please note, it has not been tested on Python 2.
The other depencies were either installed by pandas or other packages.
Ensure you have dependencies listed in requirements.txt, but note that pyobjc-framework dependencies need some clean up.