Compare commits

...

117 Commits

Author SHA1 Message Date
Jissin Mathew 70ec47df04 Fix review comments 2026-06-01 16:49:57 +05:30
Jissin Mathew 2ea77bf9b6 Implement Update Job Status for technician
<UserStory> SER1798: Update Job Status </UserStory>

<Changes>
    1. Renamed Controller and ServiceManagementService methods from completeJob to updateJobStatus for clarity and flexibility.
    2. Enhanced ServiceManagementService::updateJobStatus to support transitions:
       - STARTED → INPROGRESS
       - INPROGRESS → COMPLETED (with invoice generation and customer notification).
    3. Added INPROGRESS state to ServiceJobStatus enum and updated string conversion utilities.
    4. Introduced filterJobCards helper to generalize job filtering by status.
    5. Updated TechnicianMenu to allow technicians to select job type (Started/Inprogress) and update status accordingly.
    6. Improved job display to show current status and truncated service names for readability.
</Changes>

<Test>

 Acceptance Criteria:
 1. Technician can select a job with status STARTED and update it to INPROGRESS.
 2. Technician can select a job with status INPROGRESS and update it to COMPLETED.
 3. Completed bookings automatically generate invoices and send notifications to customers.
 4. Job status updates are reflected in the technician’s job list and customer view.

 Precondition:
 1. Technician is logged into the system.
 2. Assigned job cards exist with valid statuses (STARTED or INPROGRESS).
 3. Datastore and payment service are available.

 Steps:
 1. Navigate to Technician menu and choose "Update Job Status".
    - Verify that the system prompts for job type selection (Started/Inprogress).
 2. Select a job card from the filtered list.
    - Verify that the job card details are displayed with status.
 3. Confirm update.
    - Verify that the job status changes correctly.
 4. For jobs updated to COMPLETED:
    - Verify that the booking status is updated, invoice is generated, and notification is sent.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>

#1798
2026-06-01 16:49:56 +05:30
joelthomastrenser 972e353832 Merged PR 1152: Vehicle Service System v1.0.0.0
Features Included:

Secure access and session management with role-based authentication
Customer and technician account management
Service booking and technician assignment
Service and combo package management
Job card tracking and completion workflow
Inventory management and stock monitoring
Invoice generation and payment processing
Notification management with configurable preferences
Observer pattern based alerts for inventory, payments, and service updates
2026-06-01 16:48:25 +05:30
joelthomastrenser c5ada405e6 Merged PR 1148: Vehicle Service System
**Features Included:**
- Secure access and session management with role-based authentication
- Customer and technician account management
- Service booking and technician assignment
- Service and combo package management
- Job card tracking and completion workflow
- Inventory management and stock monitoring
- Invoice generation and payment processing
- Notification management with configurable preferences
- Observer pattern based alerts for inventory, payments, and service updates

Related work items: #1551, #1552, #1553, #1560, #1561, #1563, #1564, #1568, #1569, #1570, #1571, #1572, #1573, #1574, #1575, #1576, #1577, #1578, #1579, #1580, #1581, #1582, #1583, #1584, #1585, #1586, #1587, #1588, #1592, #1593, #1594, #1595, #1596, #1597, #1598, #1599, #1600, #1601, #1624, #1626, #1646, #1648, #1649, #1655, #1656, #1668, #1669, #1672, #1673, #1679, #1680, #1708, #1709, #1736, #1737, #1738, #1739, #1740, #1741, #1742, #1743, #1744, #1745, #1746, #1747, #1748, #1749, #1750, #1751, #1752, #1753, #1754, #1777, #1778, #1779, #1780, #1781, #1782, #1783, #1784, #1786, #1788, #1789, #1793
2026-05-29 11:50:03 +05:30
joelthomastrenser d6b4310de6 Merged PR 1142: Add display menus for users, services, combo packages and jobs
Add display menus for users, services, combo packages and jobs

Changes:
- Added display options for users, services, combo packages and technician jobs
- Updated admin and technician menu options and navigation
- Added reusable helper functions for displaying data in tabular format
- Improved user and combo package listing displays
- Fixed minor validation and error message formatting issues
2026-05-28 16:39:37 +05:30
joelthomastrenser 451085e9c2 Add display menus for users, services, combo packages and jobs
Changes:
- Added display options for users, services, combo packages and technician jobs
- Updated admin and technician menu options and navigation
- Added reusable helper functions for displaying data in tabular format
- Improved user and combo package listing displays
- Fixed minor validation and error message formatting issues
2026-05-28 16:36:34 +05:30
joelthomastrenser 4657d3e8d1 Merged PR 1139: Fix: create missing directories before file creation
Fix: create missing directories before file creation

Changes:
- Added ensureDirectoryExists() helper using _mkdir()
- Automatically create missing directories before file operations
- Added FileHelper include in FileManager
- Removed placeholder files/README.md

Fixes #1793

Related work items: #1646, #1793
2026-05-28 10:35:54 +05:30
joelthomastrenser b1b6125d88 Fix: create missing directories before file creation
Changes:
- Added ensureDirectoryExists() helper using _mkdir()
- Automatically create missing directories before file operations
- Added FileHelper include in FileManager
- Removed placeholder files/README.md

Fixes #1793
2026-05-28 10:32:36 +05:30
joelthomastrenser e739ec6ee2 Merged PR 1134: Fix Invoice Deserialization Failure for PaymentMode::NOTSET
Changes:

- Added support for PaymentMode::NOTSET in payment mode string-to-enum conversion.
- Improved invoice table column labels and spacing for better readability in invoice display screens.

Fixes #1789

Related work items: #1646, #1789
2026-05-27 19:51:59 +05:30
joelthomastrenser f78e02ed3d Fix: handle NOTSET payment mode during invoice deserialization
Changes:

- Added support for PaymentMode::NOTSET in string-to-enum conversion
  to prevent invoice deserialization failures during system startup
- Improved invoice table column labels and spacing for better readability
  and alignment in invoice display screens

Fixes #1789
2026-05-27 18:47:49 +05:30
Avinash Rajesh 807490443e Merged PR 1128: Fix customer removal flow, admin inventory UI issues, and user display improvements
Changes:

- Refactored customer and technician removal flow:
  - Ensured linked job cards and service bookings are properly cancelled.
  - Centralized cancellation logic with processBookingCancellation helper for consistent notifications, technician reassignment, and inventory restoration.
  - Prevented duplicate inventory restocking during customer removal.
  - Preserved customer references and IDs correctly during booking cancellation.

- Admin inventory management improvements:
  - Added heading output to Remove Inventory Item submenu for clearer context.
  - Prevented service creation with empty inventory selection by adding validation and early return.
  - Improved combo package creation by simplifying null checks with modern idioms.
  - Enhanced inventory selection flow:
    - Clear screen and context header for better UX.
    - Prevent duplicate item selection by checking already chosen items.
    - Changed exit option from -1 to 0 for consistency.
    - Added pressEnter prompt after successful item addition.
  - Simplified pointer checks using concise conditions (e.g., if (item)).

- User management UI fix:
  - Updated active user display in Remove User menu to include Full Name column, ensuring administrators have complete visibility when managing users.

Fixes #1788
Fixes #1778
Fixes #1781

Related work items: #1778, #1781, #1788
2026-05-27 18:38:17 +05:30
Avinash Rajesh b7bc1f574d Implement Review Fixes 2026-05-27 17:32:36 +05:30
Avinash Rajesh b25b3d59cf Fix Admin Menu Remove User Incomplete Data
- Updated active user display to include Full Name column.
- Ensured both header and row output show full name alongside ID, username, and user type.
- Improved clarity of Remove User submenu by presenting complete user information.

Fixes #1788
2026-05-27 17:12:23 +05:30
Avinash Rajesh c1bd2a6ef1 Fix Admin Inventory Management UI Issues and Workflow Enhancements
- Added heading output to Remove Inventory Item submenu for clearer user context.
- Prevented service creation with empty inventory selection by adding validation and early return.
- Improved combo package creation by simplifying null checks with modern idioms.
- Enhanced inventory selection flow:
  - Clear screen and context header for better UX.
  - Prevent duplicate item selection by checking already chosen items.
  - Changed exit option from -1 to 0 for consistency.
  - Added pressEnter prompt after successful item addition.
- Simplified pointer checks using concise conditions (e.g., if (item)).

Fixes #1778
2026-05-27 17:12:23 +05:30
Avinash Rajesh 859f7bbeaa Fix Customer Removal and Cancellation Handling Issues
- Refactored customer and technician removal flow to ensure linked job cards and service bookings are properly cancelled.
- Added inventory restoration logic to avoid duplicate restocking when cancelling bookings.
- Introduced processBookingCancellation helper for consistent cancellation handling, notifications, and technician reassignment.
- Updated UserManagementService::removeUser to invoke appropriate cancellation routines based on user type.
- Ensured customer references and IDs are preserved correctly during booking cancellation.

Fixes #1781
2026-05-27 17:12:20 +05:30
Jissin Mathew d6cc6fc04f Merged PR 1129: Fix view invoices, combo packages, and technician menu UI issues
Changes
- Added tabular invoice list with selection before full details
- Displayed Payment Mode in detailed invoice view
- Removed duplicate pressEnter() calls and improved console messages
- Changed combo package bookings to start with PENDING status
- Added filterComboPackages to list only active packages
- Improved CustomerMenu combo package selection with clearer messages and formatting
- Enhanced output with console clearing, spacing, and success feedback
- Added truncateString utility for consistent display of long names
- Updated filter functions to use reference parameters for efficiency
- Cleared console before displaying Complete Job screen
- Improved submenu header and formatting for clarity
- Prevented table headers from showing when no jobs exist
- Refined job completion flow with consistent messages

Fixes #1779
Fixes #1782
Fixes #1784

Related work items: #1779, #1782, #1784
2026-05-27 17:09:18 +05:30
Jissin Mathew 62cd7dcc89 Implement Review Fixes 2026-05-27 17:09:03 +05:30
Jissin Mathew c67bf962c1 Fix Customer Menu View Invoices UI and Navigation Issues
- Added tabular invoice list for better navigation
- Enabled user to select an invoice before viewing full details
- Displayed Payment Mode in detailed invoice view
- Removed duplicate pressEnter() calls
- Improved console messages and formatting for clarity

Fixes #1784
2026-05-27 16:55:14 +05:30
Jissin Mathew efd8b32a5f Fix Combo Package Status and Creation Flow Issues
- Changed combo package bookings to start with PENDING status
- Added filterComboPackages to list only active packages
- Improved CustomerMenu combo package selection with clearer messages and formatting
- Enhanced output with console clearing, spacing, and success feedback
- Added truncateString utility for consistent display of long names
- Updated filter functions to use reference parameters for efficiency

Fixes #1779
2026-05-27 16:53:30 +05:30
Jissin Mathew 01596e825e Fix Technician Menu Complete Job UI Issues
- Cleared console before displaying Complete Job screen
- Improved submenu header and formatting for clarity
- Prevented table headers from showing when no jobs exist
- Refined job completion flow with consistent messages

Fixes #1782
2026-05-27 16:53:29 +05:30
joelthomastrenser fb50aeba47 Merged PR 1127: Fix notification UI formatting, payment flow issues, and observer cleanup
Changes:

- Fix notification table alignment issues in admin notification screens
- Add proper spacing for notification title column display
- Remove unnecessary tab spacing from Configure Notification Preferences heading
- Change ServiceBooking ID prefix to avoid conflict with Service IDs
- Remove unnecessary newline characters from service booking completion notifications
- Detach removed users from all service observer lists during user removal
- Fix Complete Payments screen clearing immediately after heading display
- Improve table spacing in Complete Payments screen
- Prevent invalid payment mode selection from defaulting to OFFLINE mode

Fixes #1780
Fixes #1783
Fixes #1777
Fixes #1786

Related work items: #1777, #1780, #1783, #1786
2026-05-27 16:49:20 +05:30
joelthomastrenser defee9aa15 Fix ServiceBooking ID prefix and notification messages
- change ServiceBooking ID prefix from `SRV` to `SBK`
- add customer notification when technician is assigned to booking
- fix typo in job completion exception message
- remove unnecessary newline characters from completion notifications

Fixes #1780
2026-05-27 16:02:23 +05:30
joelthomastrenser 67e5917a57 Fix: improve complete payments table formatting and payment mode validation
- Increased spacing between invoice table columns for better readability
- Updated invoice table headers with clearer labels
- Prevented screen clear before invoice listing display
- Changed payment mode selection to re-prompt on invalid input instead of defaulting to offline mode
- Removed unnecessary blank line before service listing display

Fixes #1786
2026-05-27 13:02:40 +05:30
joelthomastrenser 83e2bed432 Fix: improve notification display formatting and add global exception handling
- add truncateString utility for long notification titles
- improve notification table alignment
- remove unnecessary heading spacing in notification preferences
- add application-level exception handling in UserInterface::run()

Fixes #1777
2026-05-27 12:19:34 +05:30
joelthomastrenser a9c8ec93b7 Fix: detach removed users from service observers
- detach users from InventoryManagementService observers during removal
- detach users from PaymentManagementService observers during removal
- detach users from ServiceManagementService observers during removal

Fixes #1783
2026-05-27 11:10:59 +05:30
Jissin Mathew 13b7d6d40a Merged PR 1114: Fix Admin Menu, Service Management, Technician Assignment, and Invoice Display Issues
**Changes:**

- Fixed booking status flow (PENDING → STARTED) during job card creation
- Updated purchaseService to initialize bookings with PENDING status
- Filtered active users and services before listing/selection
- Improved Assign Job flow: pending bookings only, clearer technician prompts, consistent feedback
- Enhanced View Invoices: reference parameter, empty items handling, improved formatting
- Added filterActiveServices helper for consistent active service filtering
- Fixed Remove Service to also deactivate dependent combo packages
- Improved Create Combo Packages: cancel option, confirmation step, duplicate/edge case handling
- Updated Remove Combo Package to handle empty states gracefully without exceptions

Related work items: #1646, #1740, #1744, #1745, #1747, #1749, #1752
2026-05-26 21:26:37 +05:30
joelthomastrenser 665e83d56a Implement review fixes 2026-05-26 21:25:02 +05:30
Jissin Mathew 8268b90d82 Fix Service Removal and Combo Package Management Issues
- Added ComboPackage dependency check in removeService; deactivates related packages when a service is removed.
- Added filterActiveServices helper to list only active services.
- Updated removeService and removeComboPackage with headings, empty-state checks, and consistent success/error messages.
- Enhanced createComboPackages:
  - Uses active services only.
  - Added cancel option and confirmation after first selection.
  - Prevented duplicate selection and infinite loop when limited services exist.
  - Improved feedback when all available services are selected.
- Updated selectServicesToRemove and selectComboPackage to handle empty states gracefully without exceptions.

Fixes #1749
2026-05-26 21:13:40 +05:30
Jissin Mathew 7646ce6644 Fix Assign Job to Technician issues and View invoices issues
- Assign Job to Technician:
  - Added heading for clearer user guidance.
  - Filtered only pending service bookings for assignment.
  - Improved technician listing and selection with clearer prompts.
  - Ensured booking status transitions correctly from PENDING to STARTED when job cards are created.
  - Enhanced feedback messages for technician availability and job card creation.

- View Invoices:
  - Added heading "View Invoices" for better UI consistency.
  - Updated displayInvoices to take map by reference for efficiency.
  - Improved formatting of invoice details with consistent spacing and line breaks.
  - Added handling for empty invoice parts list (shows "No inventory items used").
  - Enhanced error messages when encountering null invoices.

Fixes #1745
Fixes #1752
2026-05-26 21:13:13 +05:30
Jissin Mathew 05499e4890 Fix Create Service Submenu
- Added heading "Create Service" to submenu for clearer user guidance.
- Ensured console clears before service creation for consistent UI behavior.
- Filtered active inventory items before selection to avoid showing inactive items.
- Updated prompts with improved formatting and spacing (e.g., labour cost input, success message).
- Refactored selectInventoryItems:
  - Added "Select Required Items" heading for clarity.
  - Skipped null or inactive items during listing.
  - Improved empty inventory message ("No Items Present, Inventory empty").
  - Enhanced success and error messages with consistent line breaks.
  - Simplified logic for item selection and exit handling.

Fixes #1747
2026-05-26 21:12:17 +05:30
Jissin Mathew 3b82648e45 Fix Add Technician submenu
- Updated AdminMenu::addTechnician:
  - Added heading "Add Technician" for better user guidance.
  - Removed setw formatting, replaced with simpler prompts.
  - Ensured console clears before operation for consistency.
  - Improved error messages for password, email, and phone validation with line breaks for readability.
  - Enhanced success message with consistent spacing.
- Minor cleanup in TechnicianMenu.cpp by adding a blank line after file header for formatting consistency.

Fixed #1744
2026-05-26 21:12:16 +05:30
Jissin Mathew 937ba2e7cf Fix Add Inventory Item Issues
- Added heading "Add Inventory Item" to submenu for clearer user guidance.
- Updated option text from "Add Quantity" to "Restock Item".
- Ensured console clearing (util::clear) before add item and restock operations.
- Reformatted prompts with consistent spacing and line breaks (e.g., "Enter Item Details", "Select Item to Restock").
- Added default case handling in AdminMenu for invalid choices.
- Enhanced MenuHelper output:
  - Extra line breaks for readability.
  - Improved error messages ("Invalid index selected", "No active items available").
  - Clearer success message when updating stock with new quantity.

Fixes #1740
2026-05-26 21:12:16 +05:30
Avinash Rajesh f63e4056f2 Merged PR 1110: Fix user management, customer menu, inventory, notification, and validation issues
Changes:
- Added validation in AdminMenu::viewStockLevels and improved stock level formatting with headers, column widths, and pressEnter prompts
- Enhanced AdminMenu::checkStockAvailability with header, clear screen, and missing item validation
- Updated AdminMenu::removeUser with header and excluded ADMIN users from active list
- Improved CustomerMenu::completePayments with pending invoice checks, error handling, and clearer headers
- Refined selectInvoiceFromUserForPayment in MenuHelper.h (inline, clear screen, updated headers)
- Added "View Service History" header in CustomerMenu::viewServiceHistory and widened table columns
- Improved notification handling: added headers, empty list validation, pressEnter prompts, and adjusted column widths
- Simplified notification titles in Inventory, Payment, and Service Management services
- Strengthened UserManagementService::updateUserDetails with duplicate checks (email, phone), clearer errors, and Validator integration
- Implemented new duplicate validation functions (isUsernameDuplicate, isPhoneDuplicate, isEmailDuplicate) in Validator utilities
- Updated CustomerMenu::updateDetails with header, improved error/success message formatting, and validation integration

Related work items: #1646, #1739, #1741, #1742, #1746, #1748, #1750
2026-05-26 21:05:38 +05:30
joelthomastrenser febfa45e4a Implement review fixes
Changes:

 - Strengthened UserManagementService::updateUserDetails by checking duplicates only when email/phone are changed, preventing false errors
 - Updated AdminMenu::viewStockLevels header text from "View Stock Level" to "View Stock Levels" for consistency
 - Cleaned up CustomerMenu::updateDetails by removing unused user list retrieval and improving header/message formatting
2026-05-26 21:03:22 +05:30
Avinash Rajesh 33cbb1dac3 Fix Update Profile and User Validation Issues
- Included Validator.h in UserManagementService.cpp for duplicate checks.
- Enhanced updateUserDetails in UserManagementService to validate:
  - Throw error if user does not exist.
  - Throw error if email already exists among active users.
  - Throw error if phone number already exists among active users.
- Implemented new duplicate validation functions in Validator.cpp:
  - isUsernameDuplicate
  - isPhoneDuplicate
  - isEmailDuplicate
- Declared new duplicate validation functions in Validator.h.
- Updated CustomerMenu::updateDetails:
  - Added "Update Details" header for clarity.
  - Improved error messages with newline formatting.
  - Added success message with newline formatting.

Fixes #1746
2026-05-26 20:24:36 +05:30
Avinash Rajesh 80b91f3f1b Fix View Service History and View Notification Issue
- Updated sendNotification in InventoryManagementService, PaymentManagementService, and ServiceManagementService to use only the provided title instead of prefixing with service name.
- Added "View Service History" header in CustomerMenu::viewServiceHistory for clarity.
- Adjusted column widths in service history table for better alignment:
  - Booking ID column widened to 15.
  - Vehicle Brand, Vehicle Number, Vehicle Model, Discount %, and Status columns widened to 20.
- Updated output formatting in CustomerMenu::viewServiceHistory to match new widths.
- Added "View and Delete Notification" header in MenuHelper::viewAndDeleteNotification for clarity.
- Moved empty notification validation from selectNotification to viewAndDeleteNotification:
  - Displays "No notifications available." message.
  - Added util::pressEnter() prompt before returning when no notifications exist.
- Increased Notification title column width from 30 to 35 in selectNotification for improved readability.

Fixes #1748
2026-05-26 20:23:18 +05:30
Avinash Rajesh a87af89a8a Fix Complete Payment Issue
- Added "Complete Payments" header in CustomerMenu::completePayments for clarity.
- Implemented validation to check if invoices list is empty and display appropriate message.
- Added logic to verify presence of pending invoices before proceeding with payment.
- Enhanced error handling to show "Payment failed" with pressEnter prompt when no invoice is selected.
- Updated selectInvoiceFromUserForPayment in MenuHelper.h:
  - Changed function to inline and added util::clear() at start.
  - Updated column headers to "Technician ID" and "Technician Name" for clarity.
- Removed temporary AdminMenu.cpp file from enc_temp_folder.

Fixes #1750
2026-05-26 20:23:16 +05:30
Avinash Rajesh f1ca8c2a58 Fix Remove User Issue
- Added "Remove User" header in AdminMenu::removeUser for clarity.
- Updated filterActiveUsers in MenuHelper.h to exclude ADMIN users from the active user list.

Fixes #1742
2026-05-26 20:23:16 +05:30
Avinash Rajesh d55bbb6349 Fix Check stock availability Issue and Add error message
- Added "Check Stock Availability" header in AdminMenu::checkStockAvailability for clarity.
- Updated prompt text to "Enter the Item ID" for consistency.
- Added util::clear() after reading Item ID to refresh the screen before displaying results.
- Implemented validation to show "Item not Found" message when the entered ID does not exist in inventory.
Fix #1741
2026-05-26 20:23:15 +05:30
Avinash Rajesh ae488f5670 Fix View Stock Level and improve error messages
- Added validation in AdminMenu::viewStockLevels to check for empty inventory before displaying.
- Added validation in AdminMenu::viewStockLevels to ensure only active items are shown.
- Added "View Stock Level" header for clarity.
- Adjusted column widths for Quantity and Price to 15 for better alignment.
- Added final newline and util::pressEnter() prompt after displaying stock levels.
Fixes  #1739
2026-05-26 20:23:15 +05:30
joelthomastrenser d8f7e46180 Merged PR 1108: Fix authentication, registration, customer menu, utility, and structural issues
Changes:

- Fixed login error handling and authentication validation issues
- Added duplicate checks during customer registration
- Fixed missing headers and message formatting issues in Login/Register screens
- Improved common utility and console interaction behavior
- Fixed Select Individual Service issues (booking status and empty service handling)
- Fixed Select Combo Package issues (header and empty combo package handling)
- Fixed low stock alert loop condition bug
- Updated MenuHelper.h functions from static to inline

Related work items: #1646, #1736, #1737, #1738, #1743, #1751, #1753, #1754
2026-05-26 20:14:40 +05:30
joelthomastrenser 3d7944f77d Impelement review fixes 2026-05-26 20:12:57 +05:30
joelthomastrenser 9439202c5a Fix: improve combo package selection UI and empty state handling
- add Select a Combo Package header
- show message when no combo packages are available
- improve combo package table header labels

Fixes #1743
2026-05-26 18:04:05 +05:30
joelthomastrenser e6faa63b88 Fix: improve customer service selection flow and booking status
- Set new service bookings to PENDING instead of STARTED
- Show message when no services are available
- Add Select a Service header
- Add Enter Vehicle Details header
- Improve service selection screen flow

Fixes #1753
2026-05-26 17:46:11 +05:30
joelthomastrenser 31e660bc9e Fix: add duplicate user validation and update register customer UI
- add username duplicate validation
- add email duplicate validation
- add phone duplicate validation
- move duplicate checks to Validator utility
- add Register Customer header
- update registration success message

Fixes #1737
2026-05-26 16:47:11 +05:30
joelthomastrenser 5fd0a47459 Fix off-by-one error in sendLowStockAlerts loop
Fixes #1751
2026-05-26 14:22:41 +05:30
joelthomastrenser fb509ccb3f Change static functions to inline in MenuHelper
Fixes #1754
2026-05-26 12:40:27 +05:30
joelthomastrenser 8d07b11eae Fix login validation and improve error messages
- Check if user account is inactive before allowing login
- Add password confirmation in change password dialog
- Prevent changing password to the same value
- Standardize error messages to say "Invalid index" instead of "Invalid choice"
- Add blank line before system pause prompt
- Add "Change Password" header to change password screen
- Show error message when login fails

Fixes #1738
Fixes #1736
2026-05-26 12:18:38 +05:30
Jissin Mathew 1e11903cca Merged PR 1069: fix: cleanup and small improvements
fix: cleanup and small improvements

- added empty check in inventory alerts
- corrected parts cost calculation
- removed unused getUser method
- updated default admin password
- fixed missing includes in menus
- cleaned up MenuHelper comments
2026-05-25 20:15:26 +05:30
Jissin Mathew 19acbed1fd fix: cleanup and small improvements
- added empty check in inventory alerts
- corrected parts cost calculation
- removed unused getUser method
- updated default admin password
- fixed missing includes in menus
- cleaned up MenuHelper comments
2026-05-25 20:14:01 +05:30
Jissin Mathew 089fe496b2 Merged PR 1042: Service-Management-1553, Payment-Management-1598
**Service Management**
**SER001 - Assign Job to Technician:** Allows admins to assign service jobs to technicians for efficient work distribution.
**SER002 - Create Service:** Allows admins to create new services that customers can select and book.
**SER003 - Remove Service:** Allows admins to remove outdated services from the system.
**SER004 - View Service History:** Allows customers to view the status and history of their booked services.
**SER005 - Update Service Status:** Allows technicians to update service progress so customers can track it.

**Payment Management**
**PAY001 - Generate Invoice:** Automatically creates invoices with service, parts, and labor cost details for customer payments.
**PAY002 - Complete Payments:** Allows customers to complete pending payments and receive confirmation.
**PAY003 - View Invoices:** Allows customers to view invoice details for their purchased services.

Related work items: #1553, #1577, #1578, #1579, #1580, #1581, #1598, #1599, #1600, #1601, #1655, #1656, #1679, #1680
2026-05-25 20:07:59 +05:30
Jissin Mathew 9ee392ab3c Merge branch 'feature' into feature-1553-1598 2026-05-25 20:07:05 +05:30
Avinash Rajesh ef5125d445 Merged PR 1044: Admin-Management-1560, Inventory-Management-1552
**Admin Management**
**ADM001 - Add Technician:** Allows admins to create technician accounts for job assignments.
**ADM002 - Remove Technician or Customer:** Allows admins to remove technician or customer accounts from the system.
**ADM003 - Login:** Allows admins and technicians to securely log in to access system features.
**ADM004 - Logout:** Allows admins and technicians to securely log out of the system.
**ADM005 - Change Password:** Allows admins and technicians to update their account password for security.
**ADM006 - Create Combo Package:** Allows admins to create discounted combo service packages for customers.
**ADM007 - Remove Combo Package:** Allows admins to remove outdated combo packages from the system.

**Inventory Management**
**INV001 - View Stock Levels:** Allows admins to view current inventory stock levels and track spare part availability.
**INV002 - Add Stock:** Allows admins to add new inventory items or update stock quantities.
**INV003 - Remove Stock:** Allows admins to remove inventory items from the system.
**INV004 - Check Stock Availability:** Allows admins to check the availability of a specific stock item.

Related work items: #1552, #1560, #1573, #1574, #1575, #1576, #1582, #1583, #1584, #1585, #1586, #1587, #1588, #1668, #1669, #1672, #1673
2026-05-25 19:00:53 +05:30
joelthomastrenser 53c768bde9 Merge branch 'feature' into feature-1552-1560 2026-05-25 18:58:55 +05:30
Avinash Rajesh 45d4f693b6 Fix PR review comments and refactor menu helper logic
Changes:

- Added missing include for MenuHelper.h in project and AdminMenu
- Fixed typo in variable name inventoryIems to inventoryItems in Controller.cpp
- Removed stray semicolon from include in Controller.h
- Cleaned up duplicate comments in Controller.cpp description header
- Minor formatting adjustments with blank lines after headers in multiple files
- Updated ServiceManagementService notification message to remove informal wording
- Refactored AdminMenu::changePassword to use changePasswordHelper
- Added util::clear() call at start of viewStockLevels
- Removed redundant helper functions from AdminMenu.cpp and moved to shared helpers
- Fixed bug in removeInventoryItem to use activeItems instead of inventoryItems
- Enhanced createComboPackages to enforce selection of two distinct services
- General comment cleanup and formatting consistency across headers and implementation files
2026-05-25 17:32:17 +05:30
Jissin Mathew 1c717bb9fa Fix PR review comments
Changes:
    1. Added missing include for MenuHelper.h in project, AdminMenu, and CustomerMenu.
    2. Updated PaymentManagementService::completePayment to guard against duplicate completion by checking status before updating.
    3. Enhanced ServiceManagementService::createJobCard with null checks for inventory items and safe stock decrement logic.
    4. Added null check for job card creation in ServiceManagementService and throw runtime error if creation fails.
    5. Refactored ServiceManagementService::removeService to use m_dataStore.getServices() reference instead of getServices() copy.
    6. Renamed helper function hasAllJobCardsinServiceBookingCompleted to hasCompletedAllJobs for clarity and updated usage in completeJob.
    7. Fixed ServiceJobStatus string conversion in Enums.h to correctly return "PENDING" instead of "STARTED".
    8. Added support for parsing "PENDING" string to ServiceJobStatus::PENDING in Enums.h.
    9. Cleaned up AdminMenu.cpp by removing redundant static helper functions (listServiceBookings, selectPendingServiceBookings, listAvailableTechnicians, selectTechnician, selectInventoryItems, selectServicesToRemove).
    10. Replaced removed helpers with shared MenuHelper usage and added util::pressEnter() calls for consistent user flow.
    11. Simplified CustomerMenu.cpp by removing redundant static helpers (selectInvoiceFromUserForPayment, selectPaymentMode, displayInvoices) and moved logic to shared helpers.
    12. General formatting and comment cleanup across AdminMenu.cpp and CustomerMenu.cpp for consistency.
2026-05-25 17:31:20 +05:30
joelthomastrenser 5c23c1b9a1 Merged PR 1043: Customer-Management-1551, Notification-Management-1561, File-Management-1708
**Customer Management**
* **CUS001 - Login:** Allows customers to securely log in using valid username and password.
* **CUS002 - Logout:** Allows customers to safely log out of the system.
* **CUS003 - Change Password:** Allows customers to update their account password for security.
* **CUS004 - Customer Registration:** Allows new customers to create an account by entering personal and vehicle details.
* **CUS005 - Update Customer Details:** Allows customers to modify their saved personal information.
* **CUS006 - Select Individual Service:** Allows customers to choose and book a single vehicle service.
* **CUS007 - Select Combo Package:** Allows customers to choose and book a combo package with multiple services.

**Notification Management**
* **NOT001 - View Customer Notifications:** Allows customers to view and manage their notifications for important updates.
* **NOT002 - View Admin Notifications:** Allows admins to view and manage their notifications for important updates.
* **NOT003 - View Technician Notifications:** Allows technicians to view and manage their notifications for important updates.
* **NOT004 - Low Stock Alert:** Sends notifications to admins when inventory stock falls below the threshold.
* **NOT005 - Payment Reminder:** Sends payment reminder notifications to customers for unpaid invoices.
* **NOT006 - Configure Notifications:** Allows customers to manage notification preferences for selected services.

**File Management**
* **File Management:** Handles file-related operations such as storing, retrieving, updating, and managing files within the system.

Related work items: #1551, #1561, #1563, #1564, #1568, #1569, #1570, #1571, #1572, #1592, #1593, #1594, #1595, #1596, #1597, #1624, #1626, #1648, #1649, #1708, #1709
2026-05-25 16:05:40 +05:30
joelthomastrenser 1e8fd2829f Fix PR review comments and refactor menu helper logic
Changes:
- Added name parameter to createTechnician for consistency
- Added function headers for notification-related methods in InventoryManagementService
- Used variables for notification title and message instead of passing strings directly
- Fixed payment reminder notification message formatting
- Moved common helper functions to MenuHelper.h
- Updated CustomerMenu to use shared helper functions instead of duplicate code
- Added missing includes in MenuHelper.h
- Removed redundant helper code from CustomerMenu.cpp
- Minor formatting and comment cleanup
2026-05-25 15:46:11 +05:30
joelthomastrenser 28e4b17c63 Merge branch 'feature-file-management' into feature-1551-1561-1708 2026-05-25 14:24:21 +05:30
Jissin Mathew 6392191c14 Merge branch 'feature-payment-management' into feature-1553-1598 2026-05-25 12:11:20 +05:30
Avinash Rajesh c44b8ffd4e Merge branch 'feature-inventory-management' into feature-1552-1560 2026-05-25 12:02:30 +05:30
joelthomastrenser 72860edd18 Merge branch 'feature-notification-management' into feature-1551-1561-1708 2026-05-25 11:48:25 +05:30
Avinash Rajesh c5f87a0c68 Add standardized documentation headers 2026-05-25 10:54:35 +05:30
Jissin Mathew 014d4eaa0d Align enum string values with actual State names 2026-05-22 17:12:47 +05:30
Jissin Mathew 388e459a5a Add documentation headers across system modules 2026-05-22 16:52:06 +05:30
joelthomastrenser 53713f444b Implement serialization/deserialization and persistent storage across services
- Add serialize/deserialize support for core models
- Add file-based load/save functions in management services
- Introduce FileManager, Config, Utility and helper utilities
- Persist observer IDs for notification services
- Resolve object relationships during load (services, bookings, invoices, job cards)
- Add controller-level loadSystemData/saveSystemData
- Load data at app startup and save on shutdown
2026-05-22 16:50:28 +05:30
Jissin Mathew f1d146a37c Add documentation headers across system modules 2026-05-22 13:21:51 +05:30
Jissin Mathew 0519690043 Add documentation headers across system modules 2026-05-22 13:11:11 +05:30
Jissin Mathew 500eb95f12 Add documentation headers across system modules 2026-05-22 12:49:14 +05:30
Avinash Rajesh 6ca659c573 Add standardized documentation headers 2026-05-22 11:27:49 +05:30
Jissin Mathew 340f00deef Merge branch 'feature-notification-management-not006' into feature-notification-management 2026-05-21 21:07:17 +05:30
Jissin Mathew 0933db41a5 Merge branch 'feature-notification-management-not005' into feature-notification-management 2026-05-21 21:00:20 +05:30
Jissin Mathew 8a595a5893 Merge branch 'feature-notification-management-not004' into feature-notification-management 2026-05-21 20:54:20 +05:30
Jissin Mathew a8f934c7c5 Merge branch 'feature-notification-management-not003' into feature-notification-management 2026-05-21 20:48:41 +05:30
Jissin Mathew 166cc02aaa Merge branch 'feature-notification-management-not002' into feature-notification-management 2026-05-21 20:46:02 +05:30
joelthomastrenser b8e87ade0f Implement View Customer Notifications
<UserStory> NOT001: View Customer Notifications </UserStory>

<Changes>
1. Added shared notification helper functions to display notifications in tabular format, support notification selection, and show full notification details.
2. Implemented notification deletion logic in Controller and UserManagementService to remove notifications for the authenticated user after viewing.
3. Updated CustomerMenu::viewNotifications() to use the shared notification viewing and deletion flow.
</Changes>

<Test>

Precondition:
1. Customer is registered in the system.
2. Customer is logged into the system.
3. Customer has one or more notifications available.

Steps:
1. Navigate to “View Notifications” from the customer menu.
- Verify that the system displays the list of notifications with title and timestamp.

2. Select a notification from the displayed list.
   - Verify that the system displays the full notification details including message.

3. View the selected notification and continue.
   - Verify that the viewed notification is deleted from the system.

4. Navigate to “View Notifications” again.
   - Verify that the previously viewed notification no longer appears in the notification list.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 20:39:13 +05:30
Avinash Rajesh 7e9cc27f1c Merge branch 'feature-inventory-management-inv004' into feature-inventory-management 2026-05-21 20:14:03 +05:30
Avinash Rajesh 1377d5fb39 Merge branch 'feature-inventory-management-inv003' into feature-inventory-management 2026-05-21 20:11:55 +05:30
Avinash Rajesh d33f0aa8dc Merge branch 'feature-inventory-management-inv002' into feature-inventory-management 2026-05-21 20:09:53 +05:30
Avinash Rajesh 337fb00e1f Merge branch 'feature-admin-management-menu' into feature-admin-management 2026-05-21 19:41:39 +05:30
Avinash Rajesh 33a3677f6e Merge branch 'feature-admin-management-adm007' into feature-admin-management 2026-05-21 19:22:52 +05:30
Avinash Rajesh 3a8db0cdae Merge branch 'feature-admin-management-adm006' into feature-admin-management 2026-05-21 19:16:50 +05:30
Avinash Rajesh 7c993521a2 Merge branch 'feature-admin-management-adm005' into feature-admin-management 2026-05-21 19:10:58 +05:30
Avinash Rajesh ef2fa6d521 Merge branch 'feature-admin-management-adm004' into feature-admin-management 2026-05-21 19:06:44 +05:30
Avinash Rajesh c8647eedd9 Merge branch 'feature-admin-management-adm003' into feature-admin-management 2026-05-21 19:02:57 +05:30
Avinash Rajesh 665d9192fa Merge branch 'feature-admin-management-adm002' into feature-admin-management 2026-05-21 18:55:23 +05:30
Jissin Mathew 0adb864329 Merge branch 'feature-service-management-ser005' into feature-service-management 2026-05-21 18:34:12 +05:30
Jissin Mathew a3ad4d2e00 Merge branch 'feature-payment-management-pay003' into feature-payment-management 2026-05-21 18:11:09 +05:30
Jissin Mathew 86fd32bd2b Merge branch 'feature-service-management-ser004' into feature-service-management 2026-05-21 17:26:27 +05:30
Jissin Mathew fceb1cbec6 Merge branch 'feature-service-management-ser003' into feature-service-management 2026-05-21 17:10:53 +05:30
Jissin Mathew 53ff70a85f Merge branch 'feature-service-management-ser002' into feature-service-management 2026-05-21 16:54:07 +05:30
Jissin Mathew 4a4309d585 Merge branch 'feature-payment-management-pay002' into feature-payment-management 2026-05-21 16:20:42 +05:30
Jissin Mathew 61f70a54f6 Implement Generate Invoice
<UserStory> PAY001: Generate Invoice </UserStory>

<Changes>
    1. Added Utility.h to project configuration for supporting invoice generation utilities.
    2. Updated Invoice model to use string-based keys for parts mapping instead of integer keys.
    3. Implemented PaymentManagementService::generateInvoice to aggregate labour cost, parts cost, and apply discounts.
    4. Integrated invoice creation with Factory to instantiate Invoice objects and persist them into datastore.
    5. Enhanced Enums with PaymentMode::NOTSET to handle default invoice state.
</Changes>

<Test>

 Acceptance Criteria:
 1. Invoice auto-generates for each service booking once jobs are completed.
 2. Invoice shows a clear breakdown of charges including labour cost, parts cost, discount, and total amount.

 Precondition:
  1. Service booking exists with at least one service and required inventory items.
  2. Datastore is available for storing invoices.
  3. Payment mode and status enums are properly configured.

 Steps:
  1. Complete all jobs in a service booking.
    - Verify that PaymentManagementService::generateInvoice is triggered.
  2. Check datastore for newly created invoice.
    - Verify that invoice contains booking ID, labour cost, parts cost, discount, and total amount.
  3. Inspect invoice details.
    - Verify that breakdown of charges is accurate and discount is applied correctly.
  4. Confirm invoice status.
    - Verify that invoice is created with PaymentMode::NOTSET and PaymentStatus::PENDING.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 16:05:10 +05:30
Avinash Rajesh d161ac313c Implement Change Password Functionality
<UserStory> ADM005: Change Password </UserStory>

<Changes>
    1. Added AuthenticationManagementService::changePassword to update the authenticated user’s password with validation.
    2. Integrated Controller::changePassword to delegate password update requests to AuthenticationManagementService.
    3. Enhanced AdminMenu::changePassword to prompt for new password, validate strength using Validator, and confirm update.
    4. Added error handling to prevent password change when no user is logged in.
    5. Provided user feedback messages for invalid password attempts and successful updates.
</Changes>

<Test>

  Precondition:
  1. Admin is logged into the system.
  2. AuthenticationManagementService maintains active session.
  3. Validator is available for password strength checks.

  Steps:
  1. Navigate to Admin Menu and select "Change Password".
  2. Enter old password incorrectly.
    - Verify that system rejects the attempt and displays error.
  3. Enter new password that fails validation (length/complexity).
    - Verify that system rejects with "Error: Password is not strong enough!".
  4. Enter valid old password and strong new password.
    - Verify that system confirms "Password changed successfully" and updates the user’s password.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:12:16 +05:30
Jissin Mathew 461857f971 Implement View Invoices for Customer
<UserStory> PAY003: View Invoices </UserStory>

<Changes>
    1. Added CustomerMenu::viewInvoices to fetch invoices via Controller and display them to the customer.
    2. Implemented displayInvoices helper to show invoice details including booking, vehicle, technician, discount, total amount, invoice date, and payment status.
    3. Enhanced invoice display to include a tabular breakdown of inventory items (ItemName, Quantity, Price) used in the service.
    4. Updated ServiceBooking to store assigned technician as a const User* for richer technician details in invoice output.
</Changes>

<Test>

 Acceptance Criteria:
 1. Invoice details should show total cost and discounts.
 2. Invoice details should show list of parts used.

 Precondition:
  1. Customer is logged into the system.
  2. At least one invoice exists for the customer in the datastore.
  3. Inventory items are linked to the invoice.

 Steps:
  1. Navigate to Customer menu and choose "View Invoices".
    - Verify that the system lists invoice details including booking ID, vehicle info, technician, discount, total amount, invoice date, and payment status.
  2. Check the parts list under each invoice.
    - Verify that inventory items are displayed in tabular form with ItemName, Quantity, and Price.
  3. Confirm that discounts and total cost are shown correctly.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:09:16 +05:30
Avinash Rajesh fa08d4a90f Implement Login Functionality
<UserStory> ADM003: Login </UserStory>

<Changes>
    1. Added credential input handling in UserInterface::login with username and password prompts.
    2. Integrated Controller::login to validate credentials and retrieve authenticated user.
    3. Implemented role-based menu navigation: Admin → AdminMenu, Technician → TechnicianMenu, Customer → CustomerMenu.
    4. Added error handling for invalid credentials and unknown user types with clear feedback messages.
    5. Included util::clear for screen refresh and structured output formatting during login.
</Changes>

<Test>

  Precondition:
  1. Valid user accounts exist in the system (Admin, Technician, Customer).
  2. Controller is connected to UserManagementService for authentication.
  3. UserInterface is initialized with role-specific menus.

  Steps:
  1. Launch UserInterface and select "Login".
  2. Enter incorrect username or password.
    - Verify that system displays "Error: Invalid Username or Password".
  3. Enter valid admin credentials.
    - Verify that AdminMenu is displayed successfully.
  4. Enter valid technician or customer credentials.
    - Verify that TechnicianMenu or CustomerMenu is displayed accordingly.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:09:04 +05:30
Jissin Mathew cb3bed4050 Implement Complete Payments
<UserStory> PAY002: Complete Payments </UserStory>

<Changes>
    1. Integrated Controller with PaymentManagementService to support payment completion workflow.
    2. Implemented PaymentManagementService::completePayment with validation for invoice ID, payment mode, and status update.
    3. Enhanced CustomerMenu with helper functions to display pending invoices in tabular format and allow index-based selection.
    4. Added CustomerMenu::selectPaymentMode to capture payment mode choice (OFFLINE/ONLINE).
    5. Updated CustomerMenu::completePayments to handle invoice selection, payment mode input, and trigger payment completion via Controller.
    6. Implemented notification logic to send confirmation to customers upon successful payment.
</Changes>

<Test>

 Acceptance Criteria:
 1. Payment status marked completed.
 2. Confirmation message shown.
 3. Confirmation notification sent.

 Precondition:
  1. Customer is logged into the system.
  2. At least one pending invoice exists for the customer.
  3. Datastore is available for storing invoices and updating payment status.

 Steps:
  1. Navigate to Customer menu and choose "Complete Payments".
    - Verify that the system lists pending invoices with tabular details.
  2. Select an invoice by index.
    - Verify that the chosen invoice is retrieved correctly.
  3. Enter payment mode (OFFLINE/ONLINE).
    - Verify that the selected mode is applied to the invoice.
  4. Confirm payment completion.
    - Verify that the invoice status changes to COMPLETED.
    - Verify that a confirmation message is displayed.
    - Verify that a notification is sent to the customer.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:08:25 +05:30
Avinash Rajesh b230e3062c Implement Remove Customer or Technician Functionality
<UserStory> ADM002: Remove Technician or Customer </UserStory>

<Changes>
    1. Integrated UserManagementService and ServiceManagementService into Controller for user removal operations.
    2. Added Controller::removeUser to validate user existence, cancel related service bookings and technician jobs, and mark user inactive.
    3. Updated JobCard and ServiceBooking models to use util::ServiceJobStatus consistently and store technician references as User* instead of strings.
    4. Extended util::ServiceJobStatus enum with PENDING and CANCELLED states, including string conversion support.
    5. Implemented ServiceManagementService methods to cancel customer service bookings and technician jobs, with inventory restocking and notifications.
    6. Enhanced AdminMenu::removeUser to list active users, validate index input, confirm deletion, and invoke Controller::removeUser.
    7. Added helper functions in AdminMenu to filter active users and display them with formatted output including user type.
</Changes>

<Test>

  Precondition:
  1. Admin is logged into the system.
  2. Technician accounts exist in the system.
  3. Technician has active job assignments.

  Steps:
  1. Navigate to Admin Menu and select "Remove User".
  2. System displays list of active users with IDs, usernames, and user types.
    - Verify that inactive users are excluded from the list.
  3. Admin selects technician ID for removal.
    - Verify that system confirms deletion before proceeding.
  4. Technician is removed from job assignment list.
    - Verify that associated jobs are cancelled, inventory is restocked, and notifications are sent.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:07:25 +05:30
Avinash Rajesh 2bdf0eb741 Implement Add Technician Functionality
<UserStory> ADM001: Add Technician </UserStory>

<Changes>
    1. Added UserManagementService integration in Controller to support technician account creation.
    2. Updated Controller::createTechnician method to call createUser with util::UserType::TECHNICIAN.
    3. Renamed parameter from 'phone' to 'phoneNumber' for clarity and consistency.
    4. Enhanced AdminMenu::addTechnician with input validation for password, email, and phone number.
    5. Added success and error handling messages in AdminMenu for technician creation workflow.
</Changes>

<Test>

  Precondition:
  1. Admin is logged into the system.
  2. UserManagementService is available and connected.
  3. No existing technician account with the same username/email.

  Steps:
  1. Navigate to Admin Menu and select "Add Technician".
  2. Enter technician details (username, password, email, phone number).
    - Verify that invalid password/email/phone inputs are rejected with error messages.
  3. Enter valid technician details.
    - Verify that uniqueness is checked and duplicate accounts are not created.
  4. Submit valid details.
    - Verify that technician account is created successfully and confirmation message is displayed.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:06:32 +05:30
Avinash Rajesh ef41fec208 Implement Check Availability Status Functionality
<UserStory> INV004: Check Availability Status </UserStory>

<Changes>
    1. Updated Controller to delegate getInventoryItem calls to InventoryManagementService.
    2. Implemented InventoryManagementService::getInventoryItem to fetch items from datastore by ID.
    3. Enhanced AdminMenu with checkStockAvailability function:
       - Accepts part ID as input.
       - Retrieves item details from Controller.
       - Displays item information (ID, part name, quantity) if found and active.
       - Handles inactive or missing items gracefully.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with unique IDs.
  3. DataStore is initialized and accessible.

  Steps:
  1. Navigate to Admin Menu and select "Check Stock Availability".
    - Verify that the system prompts for an Item ID.
  2. Enter a valid Item ID for an active item.
    - Verify that the system displays the item’s details including current quantity.
  3. Enter an Item ID that does not exist.
    - Verify that the system displays “Item not found”.
  4. Enter an Item ID for an inactive item.
    - Verify that the system does not display details and indicates the item is inactive.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:04:37 +05:30
Avinash Rajesh 3594fa4f26 Implement Remove Stock Functionality
<UserStory> INV003: Remove Stock </UserStory>

<Changes>
    1. Integrated InventoryManagementService into Controller to handle removal of inventory items.
    2. Implemented InventoryManagementService::removeInventoryItem to mark items as INACTIVE in the datastore.
    3. Enhanced AdminMenu with removeInventoryItem workflow:
       - Displays inventory list with index, ID, part name, quantity, and price.
       - Allows admin to select item by index for removal.
       - Provides confirmation message after successful deletion.
    4. Added static helper function displayInventoryWithItems in AdminMenu for modularized inventory display.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with unique IDs.
  3. DataStore is initialized and accessible.

  Steps:
  1. Navigate to Admin Menu and select "Remove Inventory Item".
    - Verify that the system displays all inventory items with ID, part name, quantity, and price.
  2. Select an item by entering its index.
    - Verify that the system removes the item and displays a confirmation message.
  3. Attempt to remove an item with an invalid index.
    - Verify that the system rejects the input and shows an error message.
  4. Navigate to "View Stock Levels".
    - Verify that the removed item no longer appears in the inventory list.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:03:03 +05:30
Jissin Mathew 8162a2fe3d Implement Update Service Status
<UserStory> SER005: Update Service Status </UserStory>

<Changes>
    1. Integrated Controller with ServiceManagementService to support job completion workflow.
    2. Implemented ServiceManagementService::completeJob with validation for technician assignment, job existence, and status transition.
    3. Enhanced TechnicianMenu with job selection helper to display assigned jobs, allow index-based selection, and handle invalid choices.
    4. Updated TechnicianMenu::completeJob to mark job as completed via Controller and provide user feedback.
    5. Added logic to check if all jobs in a booking are completed, triggering invoice generation and customer notification.
</Changes>

<Test>

 Acceptance Criteria:
 1. Status updates are visible to customers immediately after technician marks job as completed.

 Precondition:
  1. Technician is logged into the system.
  2. At least one active job card is assigned to the technician.
  3. Datastore contains valid service bookings linked to jobs.

 Steps:
  1. Navigate to Technician menu and choose "Complete Job".
    - Verify that the system lists active jobs with index-based selection.
  2. Select a job card by index.
    - Verify that the job status changes from STARTED to COMPLETED.
  3. Check customer view.
    - Verify that the updated status is reflected in the customer’s booking history.
  4. If all jobs in the booking are completed:
    - Verify that an invoice is generated and a notification is sent to the customer.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:02:46 +05:30
Avinash Rajesh 6a8b845efa Implement Add Stock functionality
<UserStory> INV002: Add Stock </UserStory>

<Changes>
    1. Added Controller integration with InventoryManagementService to support adding new inventory items and updating existing stock quantities.
    2. Implemented InventoryManagementService::addInventoryItem to create new items via Factory and insert them into the DataStore.
    3. Implemented InventoryManagementService::addInventoryItemStock to update stock quantities for existing items.
    4. Enhanced AdminMenu with options to add new items or update stock quantities, including input validation and confirmation messages.
    5. Added helper functions in AdminMenu to display inventory items and handle quantity updates interactively.
    6. Included necessary headers (InventoryItem, Factory, iomanip) for new functionality.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains existing items with unique IDs.
  3. DataStore is accessible and initialized.

  Steps:
  1. Navigate to Admin Menu and select "Add Inventory Item".
    - Verify that the system prompts for part name, quantity, and price.
  2. Enter details for a new item with a unique part name and ID.
    - Verify that the item is successfully added and a confirmation message is displayed.
  3. Attempt to add an item with a duplicate ID.
    - Verify that the system rejects the duplicate and displays an error message.
  4. Select "Add Quantity" option for an existing item.
    - Verify that the system updates the stock quantity and displays the new total in the confirmation message.
  5. Navigate to "View Stock Levels".
    - Verify that the updated stock quantity is reflected in the inventory list.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:00:59 +05:30
Jissin Mathew fc7bb2569b Implement View Service History
<UserStory> SER004: View Service History </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to fetch service bookings by customer ID.
    2. Enhanced ServiceBooking model to store technician as a User* instead of a string for richer details.
    3. Implemented Controller::getServiceBookingsByUser to return a read-only map of bookings for safe access.
    4. Updated CustomerMenu::viewServiceHistory to display bookings in tabular format with aligned columns.
    5. Added condition check to show technician name if assigned, otherwise display "Not Assigned".
    6. Included booking status and discount percentage in the service history output.
</Changes>

<Test>

 Acceptance Criteria:
 1. System should fetch real-time status.
 2. Status should update automatically when technician changes it.
 3. Customer should be able to view history.

  Precondition:
  1. Customer is logged into the console application.
  2. At least one active service booking exists for the customer.
  3. Technician has permission to update booking status.

  Steps:
  1. Navigate to Customer menu and choose "View Service History".
    - Verify that the console displays current booking status along with technician assignment.
  2. Technician updates the status of a booking.
    - Verify that the console view reflects the updated status automatically.
  3. Customer views service history again.
    - Verify that the history shows the latest status changes.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:59:18 +05:30
Avinash Rajesh 9f882610b3 Implement View Stock Level Functionality
<UserStory> INV001: View Stock Level </UserStory>

<Changes>
    1. Integrated InventoryManagementService into Controller to provide read-only access to inventory items.
    2. Added implementation for InventoryManagementService::getInventoryItems to fetch data from DataStore.
    3. Enhanced AdminMenu with viewStockLevels functionality to display inventory details (ID, part name, quantity, price).
    4. Updated NotificationManagementService interface to provide concrete implementations for sendNotification, attach, detach, and notify methods.
    5. Included necessary headers (InventoryItem, InventoryManagementService, iomanip) for new functionality.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with varying stock levels.
  3. Notification service is active and users are registered.

  Steps:
  1. Navigate to Admin Menu and select "View Stock Levels".
    - Verify that the system displays all inventory items with ID, part name, quantity, and price.
  2. Check items with sufficient stock.
    - Verify that they are displayed normally without highlighting.
  3. Check items with low stock threshold.
    - Verify that these items are highlighted to indicate low availability.
  4. Trigger a notification for a low-stock item.
    - Verify that the notification is sent to registered users successfully.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 14:57:16 +05:30
Jissin Mathew 70e1ef66d4 Implement Remove Service for admin
<UserStory> SER003: Remove Service </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to support service removal.
    2. Implemented ServiceManagementService::removeService with validation for service existence and marking as INACTIVE.
    3. Enhanced Controller::getServices to return a read-only map of services for safe UI access.
    4. Added AdminMenu::selectServicesToRemove helper to list active services in tabular format and capture user choice.
    5. Updated AdminMenu::removeService to prompt for service selection, delegate removal to Controller, and display success/failure messages.
</Changes>

<Test>

 Acceptance Criteria:
 1. Admin selects service ID.
 2. System confirms deletion.
 3. Service removed from customer menu.

  Precondition:
  1. Admin is logged into the system.
  2. At least one active service exists in the datastore.
  3. Customer menu displays available services.

  Steps:
  1. Navigate to Admin menu and choose "Remove Service".
    - Verify that the system lists active services in tabular format.
  2. Select a service ID from the list.
    - Verify that the system confirms deletion.
  3. Check customer menu.
    - Verify that the removed service no longer appears.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:54:33 +05:30
Jissin Mathew e7f1b51d05 Implement Create Service for admin
<UserStory> SER002: Create Service </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to support service creation.
    2. Implemented ServiceManagementService::createService with validation for duplicate service IDs and insertion into datastore.
    3. Enhanced AdminMenu with selectInventoryItems helper to display inventory in tabular format, allow selection, and handle exit condition.
    4. Updated AdminMenu::createService to prompt for service name, allow inventory selection, capture labour cost, and create service via Controller.
</Changes>

<Test>

 Acceptance Criteria:
 1. Admin enters new service name.
 2. Admin selects required parts for the services.
 3. Service created and visible to customers.

  Precondition:
  1. Admin is logged into the system.
  2. Inventory contains at least one active item.
  3. Datastore is available for storing services.

  Steps:
  1. Navigate to Admin menu and choose "Create Service".
    - Verify that the system prompts for service name.
  2. Select inventory items from the tabular list.
    - Verify that inactive items are skipped and active items can be added.
  3. Enter labour cost and confirm creation.
    - Verify that the service is created successfully and stored in datastore.
  4. Check customer view.
    - Verify that the newly created service is visible to customers.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:51:59 +05:30
Jissin Sam Mathew 9b7d9cf7c1 Implement Assign Job to Technician functionality
<UserStory> SER001: Assign job to technician </UserStory>

<Changes>
    1. Added ServiceManagementService logic to retrieve service bookings and create job cards for assigned technicians.
    2. Added UserManagementService support to retrieve technicians by user type and fetch technician details by ID.
    3. Connected Controller methods with ServiceManagementService and UserManagementService for service booking retrieval, technician listing, and job card creation.
    4. Updated JobCard model to use util::ServiceJobStatus consistently and simplified constructor initialization for assigned and completion timestamps.
    5. Added PENDING status in ServiceJobStatus enum for identifying unassigned service bookings.
    6. Implemented AdminMenu job assignment flow to list pending service bookings, display available technicians, allow technician selection, and assign jobs for services in the booking.
    7. Added notification trigger during job card creation for assigned technicians.
</Changes>

<Test>

Job assignment functionality validation

Precondition:
1. System is running.
2. Pending service bookings are available in the system.
3. Technician users are available in the system.
4. Admin user is logged in and admin menu is active.

Steps:
1. Launch the application and log in as an admin.
2. Select the Assign Job option from the admin menu.
3. View the list of available pending service bookings.
   - Verify that pending bookings are displayed.
4. Select a valid service booking.
5. View the list of available technicians.
   - Verify that technicians are listed for selection.
6. Select a technician to assign the job.
   - Verify that job cards are created for services in the booking.
   - Verify that assigned jobs are visible in the technician’s menu.
   - Verify that a confirmation message is shown.
   - Verify that a confirmation notification is sent to the assigned technician.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:50:43 +05:30
Avinash Rajesh a6e19017ca Implement Create Combo Package Functionality
<UserStory> ADM006:Create Combo Package </UserStory>

<Changes>
    1. Added ServiceManagementService::createComboPackage to validate package name, included services, and discount percentage before creation.
    2. Integrated Controller::createComboPackage to delegate combo package creation to ServiceManagementService.
    3. Enhanced AdminMenu::createComboPackages to allow admin input for package name, service selection, and discount percentage.
    4. Implemented service validation to ensure only active services are selectable and that duplicate combos are prevented.
    5. Added formatted output for service listing with cost calculation and confirmation messages upon successful package creation.
</Changes>

<Test>

  Precondition:
  1. Admin is logged into the system.
  2. At least two active services exist in the system.
  3. ServiceManagementService is connected to DataStore for services and combo packages.

  Steps:
  1. Navigate to Admin Menu and select "Create Combo Package".
  2. Enter package name, select two active services, and provide discount percentage.
    - Verify that system validates service IDs and ensures discount is between 0 and 100.
  3. Attempt to create a package with invalid service IDs or duplicate services.
    - Verify that system rejects with appropriate error messages.
  4. Enter valid package details.
    - Verify that combo package is saved successfully and visible to customers.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 13:08:24 +05:30
Avinash Rajesh ab6eed5ee6 Implement Remove Combo Package for admin
<UserStory> SER003: Remove Combo Package </UserStory>

<Changes>

Added integration between Controller and ServiceManagementService to support combo package removal.

Implemented ServiceManagementService::removeComboPackage with validation for package ID and marking state as INACTIVE.

Enhanced AdminMenu with displayComboPackagesWithIndex helper to show packages in tabular format with index.

Updated AdminMenu::selectComboPackage to allow selection of active packages only and return selected package ID.

Updated AdminMenu::removeComboPackage to prompt for selection, confirm removal, and provide success/failure feedback.
</Changes>

<Test>

Acceptance Criteria:

Admin selects package ID.

System confirms deletion.

Package removed from customer menu.

Precondition:

Admin is logged into the system.

At least one active combo package exists.

Datastore is available for storing combo packages.

Steps:

Navigate to Admin menu and choose "Remove Combo Package".

Verify that the system displays available active packages in tabular format with index.

Select a package ID from the list.

Verify that inactive packages are skipped and only active ones are selectable.

Confirm removal.

Verify that the package is marked INACTIVE and removed from customer menu.

Check customer view.

Verify that the removed package is no longer visible to customers.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 12:44:00 +05:30
joelthomastrenser b9be43acca Implement Payment Reminder functionality
<UserStory>
NOT005: Payment Reminder
</UserStory>

<Changes>
    1. Added payment reminder check in Controller::runSystemChecks() to trigger reminder processing during system startup.
    2. Implemented PaymentManagementService::sendPaymentReminders() to identify unpaid invoices that exceed the pending payment threshold and send reminder notifications to customers.
    3. Added reminder notification logic to include invoice details and stop reminders once invoice payment status changes from Pending to Paid.
</Changes>

<Test>
    Precondition:
    1. Customer has an invoice with PaymentStatus::PENDING.
    2. Invoice age exceeds the configured payment reminder threshold.
    3. Application is started and system checks execute.

    Steps:
    1. Start the application.
    2. Allow system checks to run during startup.
    3. Navigate to View Notifications.
       - Verify that a payment reminder notification is displayed.
    4. Open the generated notification.
       - Verify that the notification includes the invoice ID and due date.
    5. Complete payment for the invoice and restart the application.
       - Verify that no further reminder notifications are generated for the paid invoice.
</Test>

<Review>
    Sreeja Reghukumar, please review
</Review>
2026-05-21 12:25:45 +05:30
joelthomastrenser aef0f4146e Implement Low Stock Alert functionality
<UserStory> NOT004: Low Stock Alert </UserStory>

<Changes>
    1. Added low stock alert check in Controller::runSystemChecks() to trigger inventory notification processing during system startup.
    2. Implemented InventoryManagementService::sendLowStockAlerts() to detect inventory items below threshold, identify admin users, and send low stock alert notifications with item details.
    3. Added helper logic to notify all admins when low stock inventory is detected.

</Changes>

<Test>

    Precondition:
    1. System has at least one admin user.
    2. Inventory item exists with quantity below the configured low stock threshold.
    3. Application is started and system checks execute.

    Steps:
    1. Start the application.
    2. Allow system checks to run during startup.
    3. Navigate to Inventory Menu / View Notifications.
       - Verify that a low stock alert notification is displayed.
    4. Open the generated notification.
       - Verify that the notification includes the part name and remaining quantity.
    5. Confirm notification content.
       - Verify that the alert was triggered only for inventory items with stock below the threshold.

</Test>

<Review>
    Sreeja Reghukumar, please review
</Review>
2026-05-21 12:20:39 +05:30
joelthomastrenser 454af1b4ef Implement Admin and Technician Menus
Changes:
  - Added Admin Menu display with menu options
  - Added Technician Menu display with menu options
  - Added menu choice handling using switch case
  - Connected menu options to corresponding functions
  - Added invalid choice message
  - Added logout handling
  - Added missing function declarations in TechnicianMenu header
2026-05-21 10:46:23 +05:30
Avinash Rajesh df769a7528 Implement Logout functionality
<UserStory> ADM004: Logout </UserStory>

<Changes>
    1. Added AuthenticationManagementService::logout to clear authenticated user session.
    2. Integrated logout handling in Controller::logout to delegate session termination.
    3. Updated AdminMenu::logout and TechnicianMenu::logout to call Controller::logout for consistent session management.
    4. Extended TechnicianMenu.h with logout method declaration.
    5. Ensured session termination returns control to main menu after logout.
</Changes>

<Test>

  Precondition:
  1. User is logged into the system (Admin or Technician).
  2. AuthenticationManagementService maintains active session.
  3. Controller is connected to AuthenticationManagementService.

  Steps:
  1. Navigate to Admin or Technician Menu.
  2. Select "Logout" option.
    - Verify that AuthenticationManagementService::logout clears authenticated user.
  3. Session is terminated.
    - Verify that system confirms logout and invalidates session.
  4. Console returns to main menu.
    - Verify that user is redirected to main menu and must log in again to continue.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 10:39:53 +05:30
joelthomastrenser c92ad773c7 Implement Configure Notifications functionality
<UserStory> NOT006: Configure Notifications </UserStory>

<Changes>
    1. Added notification subscription configuration in CustomerMenu to allow customers to enable or disable notifications for Payment Management Service and Service Management Service.
    2. Updated Controller::configureNotifications() to attach or detach the authenticated user from service observers based on selected notification preferences.
    3. Refactored Observer interface and User notification handling to support notification delivery through observer subscriptions.
    4. Implemented observer attach, detach, and sendNotification logic in InventoryManagementService, PaymentManagementService, and ServiceManagementService to ensure notifications are sent only to subscribed users.

</Changes>

<Test>

    Precondition:
    1. Customer user is logged into the system.
    2. Notification configuration option is available in Customer Menu.
    3. Notification-triggering event exists for Payment Management Service or Service Management Service.

    Steps:
    1. Navigate to Configure Notification Preferences in Customer Menu.
    2. Enable notifications for one service and disable notifications for the other.
    3. Trigger a notification event for both services.
       - Verify that notification is received only from the subscribed service.
    4. Change preferences by disabling the subscribed service and enabling the other.
    5. Trigger notification events again.
       - Verify that notification is received only from the newly subscribed service.

</Test>

<Review>
    Sreeja Reghukumar, please review
</Review>
2026-05-20 19:55:54 +05:30
joelthomastrenser 713c3b6cf9 Implement View Technician Notifications
<UserStory> NOT003: View Technician Notifications </UserStory>

<Changes>
    1. Added MenuHelper.h to the project for shared notification viewing helper support.
    2. Updated TechnicianMenu.cpp to include MenuHelper.h and route viewNotifications() through the shared notification handler.
</Changes>

<Test>

    Precondition:
    1. Technician user exists and is logged into the system.
    2. Technician has one or more notifications available.
    3. “View Notifications” option is visible in the Technician menu.

    Steps:
    1. Navigate to Technician Menu.
    2. Select “View Notifications”.
    3. Verify that the system displays a list of notifications showing title, message, and timestamp.
    4. Select a notification to view full details.
       - Verify that the selected notification is displayed and deleted after viewing.
    5. Return to the notification list or reopen “View Notifications”.
       - Verify that the previously viewed notification is no longer present.

</Test>

<Review>
    Sreeja Reghukumar, please review
</Review>
2026-05-20 16:24:34 +05:30
joelthomastrenser 1732776d13 Implement View Admin Notifications
<UserStory> NOT002: View Admin Notifications </UserStory>

<Changes>
    1. Added shared notification view handler `viewAndDeleteNotification()` in MenuHelper.h for notification viewing and deletion logic reuse.
    2. Updated AdminMenu.cpp to include MenuHelper.h and connected AdminMenu::viewNotifications() to the shared notification handler.
</Changes>

<Test>

    Precondition:
    1. Admin user exists and is logged into the system.
    2. Admin has one or more notifications available.
    3. “View Notifications” option is visible in the Admin menu.

    Steps:
    1. Navigate to Admin Menu.
    2. Select “View Notifications”.
    3. Verify that the system displays a list of notifications showing title, message, and timestamp.
    4. Select a notification to view full details.
       - Verify that the selected notification is displayed and deleted after viewing.
    5. Return to the notification list or reopen “View Notifications”.
       - Verify that the previously viewed notification is no longer present.

</Test>

<Review>
    Sreeja Reghukumar, please review
</Review>
2026-05-20 16:10:04 +05:30
55 changed files with 8037 additions and 364 deletions
@@ -1,7 +1,24 @@
/*
File: Trenser.VehicleServiceSystem.cpp
Description: Entry point for the Vehicle Service Management System.
Initializes the UserInterface and starts the application loop.
Author: Trenser
Date: 19-May-2026
*/
#include "UserInterface.h"
/*
Function: main
Description: The main entry point of the application.
Creates a UserInterface object and invokes the run method to start the system.
Parameters:
- None
Returns:
- int: Exit status code (0 for successful execution).
*/
int main()
{
UserInterface userInterface;
userInterface.run();
}
}
@@ -173,9 +173,12 @@
<ClInclude Include="services\UserManagementService.h" />
<ClInclude Include="utilities\Config.h" />
<ClInclude Include="utilities\Enums.h" />
<ClInclude Include="utilities\FileHelper.h" />
<ClInclude Include="utilities\FileManager.h" />
<ClInclude Include="utilities\InputHelper.h" />
<ClInclude Include="utilities\Map.h" />
<ClInclude Include="utilities\OutputHelper.h" />
<ClInclude Include="utilities\StringHelper.h" />
<ClInclude Include="utilities\Timestamp.h" />
<ClInclude Include="utilities\Utility.h" />
<ClInclude Include="utilities\Validator.h" />
@@ -233,5 +233,23 @@
<ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter>
</ClInclude>
<ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\FileManager.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\StringHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -6,10 +6,16 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "ComboPackage.h"
#include "Controller.h"
#include "Enums.h"
#include "InventoryItem.h"
#include "Invoice.h"
#include "JobCard.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "User.h"
#include <stdexcept>
/*
Function: login
@@ -55,6 +61,7 @@ Parameter: const std::string& username - customer
const std::string& phone - customers phone number
Return type: void
*/
void Controller::createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone)
{
m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER);
@@ -71,8 +78,19 @@ const User* Controller::getAuthenticatedUser()
return m_authenticationManagementService.getAuthenticatedUser();
}
void Controller::createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
/*
Function: createTechnician
Description: Creates a new technician account with provided details by
delegating to the user management service.
Parameter: const std::string& username - technician's username
const std::string& password - technician's password
const std::string& email - technician's email address
const std::string& phoneNumber - technician's phone number
Return type: void
*/
void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber)
{
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
}
/*
@@ -92,14 +110,45 @@ void Controller::updateUserDetails(const std::string& email, const std::string&
m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone);
}
/*
Function: getServices
Description: Retrieves all available services in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const Service*> containing all services
*/
util::Map<std::string, const Service*> Controller::getServices()
{
return util::Map<std::string, const Service*>();
util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices();
util::Map<std::string, const Service*> readOnlyServices;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
readOnlyServices.insert(currentServices.getValueAt(iterator)->getId(), currentServices.getValueAt(iterator));
}
return readOnlyServices;
}
/*
Function: getComboPackages
Description: Retrieves all available combo packages from the service
management service and constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const ComboPackage*>
*/
util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
{
return util::Map<std::string, const ComboPackage*>();
util::Map<std::string, ComboPackage*> currentAvailableComboPackages = m_serviceManagementService.getComboPackages();
util::Map<std::string, const ComboPackage*> readOnlyComboPackages;
for (int iterator = 0; iterator < currentAvailableComboPackages.getSize(); iterator++)
{
ComboPackage* currentComboPackage = currentAvailableComboPackages.getValueAt(iterator);
if (currentComboPackage)
{
readOnlyComboPackages.insert(currentComboPackage->getId(), currentComboPackage);
}
}
return readOnlyComboPackages;
}
/*
@@ -130,97 +179,427 @@ void Controller::purchaseComboPackage(const std::string& comboPackageID, const s
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
}
/*
Function: getInventoryItems
Description: Retrieves all inventory items from the inventory management service
and constructs a read-only map for external use.
Parameter: None
Return type: util::Map<std::string, const InventoryItem*>
*/
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{
return util::Map<std::string, const InventoryItem*>();
auto inventoryItems = m_inventoryManagementService.getInventoryItems();
util::Map<std::string, const InventoryItem*> readOnlyInventoryItems;
int inventoryItemsMapSize = inventoryItems.getSize();
for (int index = 0; index < inventoryItemsMapSize; index++)
{
readOnlyInventoryItems.insert(inventoryItems.getKeyAt(index), inventoryItems.getValueAt(index));
}
return readOnlyInventoryItems;
}
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the inventory management service.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: const InventoryItem*
*/
const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID)
{
return nullptr;
return m_inventoryManagementService.getInventoryItem(inventoryItemID);
}
/*
Function: addInventoryItem
Description: Adds a new inventory item with specified details to the inventory management service.
Parameter: const std::string& partName - name of the part
int quantity - quantity of the part
double price - price of the part
Return type: void
*/
void Controller::addInventoryItem(const std::string& partName, int quantity, double price)
{
m_inventoryManagementService.addInventoryItem(partName, quantity, price);
}
/*
Function: removeInventoryItem
Description: Removes an inventory item from the inventory management service by its ID.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void Controller::removeInventoryItem(const std::string& inventoryItemID)
{
m_inventoryManagementService.removeInventoryItem(inventoryItemID);
}
/*
Function: addInventoryItemStock
Description: Adds stock to an existing inventory item in the inventory management service.
Parameter: const std::string& selectedItemId - ID of the inventory item
int quantity - quantity to add
Return type: void
*/
void Controller::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity);
}
/*
Function: getServiceBookings
Description: Retrieves all service bookings in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const ServiceBooking*> containing service bookings
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{
return util::Map<std::string, const ServiceBooking*>();
auto serviceBookings = m_serviceManagementService.getServiceBookings();
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookings;
for (int iterator = 0; iterator < serviceBookings.getSize(); iterator++)
{
readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator));
}
return readOnlyServiceBookings;
}
/*
Function: getServiceBookingsByUser
Description: Retrieves all service bookings for a specific user.
Parameters:
- userID: std::string, the user ID
Returns:
- util::Map<std::string, const ServiceBooking*> containing bookings for the user
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{
return util::Map<std::string, const ServiceBooking*>();
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap;
util::Map<std::string, ServiceBooking*> currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID);
for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++)
{
readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator));
}
return readOnlyServiceBookingsByUserMap;
}
/*
Function: getUsers
Description: Retrieves all users from the user management service and
constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const User*>
*/
util::Map<std::string, const User*> Controller::getUsers()
{
return util::Map<std::string, const User*>();
auto listOfUsers = m_userManagementService.getUsers();
util::Map<std::string, const User*> readOnlyUserList;
for (int iterator = 0; iterator < listOfUsers.getSize(); iterator++)
{
readOnlyUserList.insert(listOfUsers.getKeyAt(iterator), listOfUsers.getValueAt(iterator));
}
return readOnlyUserList;
}
/*
Function: getUsers
Description: Retrieves users filtered by user type.
Parameters:
- userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN)
Returns:
- util::Map<std::string, const User*> containing users of the specified type
*/
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{
return util::Map<std::string, const User*>();
auto userMap = m_userManagementService.getUsers(userType);
util::Map<std::string, const User*> readOnlyUserMap;
for (int iterator = 0; iterator < userMap.getSize(); iterator++)
{
readOnlyUserMap.insert(userMap.getKeyAt(iterator), userMap.getValueAt(iterator));
}
return readOnlyUserMap;
}
/*
Function: createJobCard
Description: Creates a job card for a service booking assigned to a technician.
Parameters:
- bookingID: std::string, ID of the service booking
- technicianID: std::string, ID of the technician
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{
m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID);
}
/*
Function: createService
Description: Creates a new service with associated inventory items and labor cost.
Parameters:
- name: std::string, name of the service
- inventoryItemIDs: Vector of inventory item IDs
- laborCost: double, labor cost
Returns:
- void
*/
void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{
m_serviceManagementService.createService(name, inventoryItemIDs, laborCost);
}
/*
Function: removeService
Description: Removes a service from the system by ID.
Parameters:
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::removeService(const std::string& serviceID)
{
m_serviceManagementService.removeService(serviceID);
}
/*
Function: getJobCardsByUser
Description: Retrieves job cards assigned to the authenticated technician.
Parameters:
- None
Returns:
- util::Map<std::string, const JobCard*> containing job cards
*/
util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{
return util::Map<std::string, const JobCard*>();
const User* currentUser = getAuthenticatedUser();
auto jobCardsAssignedToTechnician = m_serviceManagementService.getJobCards(currentUser->getId());
util::Map<std::string, const JobCard*> readOnlyJobCardMap;
for (int iterator = 0; iterator < jobCardsAssignedToTechnician.getSize(); iterator++)
{
JobCard* currentJobCard = jobCardsAssignedToTechnician.getValueAt(iterator);
readOnlyJobCardMap.insert(currentJobCard->getId(), currentJobCard);
}
return readOnlyJobCardMap;
}
void Controller::completeJob(const std::string& jobID)
/*
Function: completeJob
Description: Marks a job card as completed.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
*/
void Controller::updateJobStatus(const std::string& jobID)
{
m_serviceManagementService.updateJobStatus(jobID);
}
/*
Function: removeUser
Description: Removes a user by ID. Cancels associated service bookings
and technician jobs before removing the user from the system.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void Controller::removeUser(const std::string& userID)
{
User* user = m_userManagementService.getUser(userID);
if (!user)
{
throw std::runtime_error("Error: User not Found.\n");
}
m_userManagementService.removeUser(userID);
}
/*
Function: createComboPackage
Description: Creates a new combo package with specified services and discount
percentage by delegating to the service management service.
Parameter: const std::string& name - name of the combo package
const util::Vector<std::string>& serviceIDs - list of service IDs
double discountPercentage - discount percentage for the package
Return type: void
*/
void Controller::createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage)
{
m_serviceManagementService.createComboPackage(name, serviceIDs, discountPercentage);
}
/*
Function: removeComboPackage
Description: Removes a combo package by ID by delegating to the service
management service.
Parameter: const std::string& comboPackageID - ID of the combo package
Return type: void
*/
void Controller::removeComboPackage(const std::string& comboPackageID)
{
m_serviceManagementService.removeComboPackage(comboPackageID);
}
/*
Function: getInvoicesByUser
Description: Retrieves all invoices associated with the currently authenticated user.
Converts them into a read-only map before returning.
Parameters:
- None
Returns:
- util::Map<std::string, const Invoice*> containing the users invoices
*/
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
{
return util::Map<std::string, const Invoice*>();
User* currentUser = m_authenticationManagementService.getAuthenticatedUser();
util::Map<std::string, Invoice*> currentUserInvoices = m_paymentManagementService.getInvoices(currentUser->getId());
util::Map<std::string, const Invoice*> userInvoicesReadOnly;
for (int iterator = 0; iterator < currentUserInvoices.getSize(); iterator++)
{
Invoice* currentInvoice = currentUserInvoices.getValueAt(iterator);
userInvoicesReadOnly.insert(currentInvoice->getId(), currentInvoice);
}
return userInvoicesReadOnly;
}
/*
Function: completePayment
Description: Completes payment for a specific invoice using the given payment mode.
Parameters:
- invoiceID: std::string, ID of the invoice to be paid
- paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE)
Returns:
- void
*/
void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{
m_paymentManagementService.completePayment(invoiceID, paymentMode);
}
/*
Function: getNotifications
Description: Retrieves all notifications for the currently authenticated user.
Converts them into a read-only vector before returning.
Parameters: None
Return type: util::Vector<const Notification*>
*/
util::Vector<const Notification*> Controller::getNotifications()
{
return util::Vector<const Notification*>();
const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (!authenticatedUser)
{
throw std::runtime_error("No user is currently logged in!");
}
auto notifications = m_userManagementService.getUserNotifications(authenticatedUser->getId());
int numberOfNotifications = notifications.getSize();
util::Vector<const Notification*> readOnlyNotifications;
for (int index = 0; index < numberOfNotifications; index++)
{
readOnlyNotifications.push_back(notifications[index]);
}
return readOnlyNotifications;
}
/*
Function: deleteNotification
Description: Deletes a specific notification for the currently authenticated user.
Parameters:
- notificationID: std::string, the unique identifier of the notification
Return type: void
*/
void Controller::deleteNotification(const std::string& notificationID)
{
const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (!authenticatedUser)
{
throw std::runtime_error("No user is currently logged in!");
}
m_userManagementService.deleteNotification(notificationID, authenticatedUser->getId());
}
void Controller::configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications)
/*
Function: configureNotifications
Description: Configures notification preferences for the authenticated user.
Attaches or detaches the user from payment and service notifications.
Parameters:
- paymentNotifications: bool, enable/disable payment notifications
- serviceNotifications: bool, enable/disable service notifications
Return type: void
*/
void Controller::configureNotifications(bool paymentNotifications, bool serviceNotifications)
{
User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser)
{
if (paymentNotifications)
{
m_paymentManagementService.attach(authenticatedUser);
}
else
{
m_paymentManagementService.detach(authenticatedUser);
}
if (serviceNotifications)
{
m_serviceManagementService.attach(authenticatedUser);
}
else
{
m_serviceManagementService.detach(authenticatedUser);
}
}
else
{
throw std::runtime_error("No user is currently logged in!");
}
}
/*
Function: loadSystemData
Description: Loads all system data from persistent storage into memory.
Invokes the respective management services to load users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::loadSystemData()
{
m_userManagementService.loadUsers();
m_inventoryManagementService.loadInventoryItems();
m_serviceManagementService.loadServices();
m_serviceManagementService.loadComboPackages();
m_serviceManagementService.loadServiceBookings();
m_serviceManagementService.loadJobCards();
m_paymentManagementService.loadInvoices();
m_serviceManagementService.loadObservers();
m_paymentManagementService.loadObservers();
m_inventoryManagementService.loadObservers();
}
/*
Function: saveSystemData
Description: Saves all system data from memory back to persistent storage.
Invokes the respective management services to save users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::saveSystemData()
{
m_userManagementService.saveUsers();
m_inventoryManagementService.saveInventoryItems();
m_serviceManagementService.saveServices();
m_serviceManagementService.saveComboPackages();
m_serviceManagementService.saveServiceBookings();
m_serviceManagementService.saveJobCards();
m_paymentManagementService.saveInvoices();
m_serviceManagementService.saveObservers();
m_paymentManagementService.saveObservers();
m_inventoryManagementService.saveObservers();
}
/*
@@ -232,5 +611,7 @@ Return type: void
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists();
m_inventoryManagementService.sendLowStockAlerts();
m_paymentManagementService.sendPaymentReminders();
}
@@ -1,18 +1,21 @@
/*
File: Controller.h
Description: Header file declaring the Controller class, which coordinates
authentication, user management, service management, inventory,
and notifications across the Vehicle Service System.
Description: Header file declaring the Controller class, which manages
user authentication, inventory, services, bookings, job cards,
invoices, and notifications in the system.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Map.h"
#include <string>
#include "Enums.h"
#include "AuthenticationManagementService.h"
#include "UserManagementService.h"
#include "Enums.h"
#include "InventoryManagementService.h"
#include "Map.h"
#include "PaymentManagementService.h"
#include "ServiceManagementService.h"
#include "UserManagementService.h"
class Service;
class ComboPackage;
@@ -26,16 +29,18 @@ class Notification;
class Controller
{
private:
AuthenticationManagementService m_authenticationManagementService;
AuthenticationManagementService m_authenticationManagementService;
UserManagementService m_userManagementService;
ServiceManagementService m_serviceManagementService;
ServiceManagementService m_serviceManagementService;
InventoryManagementService m_inventoryManagementService;
PaymentManagementService m_paymentManagementService;
public:
bool login(const std::string& username, const std::string& password);
void logout();
void changePassword(const std::string& newPassword);
void createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone);
const User* getAuthenticatedUser();
void createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone);
void createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone);
void updateUserDetails(const std::string& email, const std::string& phone);
util::Map<std::string, const Service*> getServices();
util::Map<std::string, const ComboPackage*> getComboPackages();
@@ -44,6 +49,7 @@ public:
util::Map<std::string, const InventoryItem*> getInventoryItems();
const InventoryItem* getInventoryItem(const std::string& inventoryItemID);
void addInventoryItem(const std::string& partName, int quantity, double price);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void removeInventoryItem(const std::string& inventoryItemID);
util::Map<std::string, const ServiceBooking*> getServiceBookings();
util::Map<std::string, const ServiceBooking*> getServiceBookingsByUser(const std::string userID);
@@ -53,7 +59,7 @@ public:
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID);
util::Map<std::string, const JobCard*> getJobCardsByUser();
void completeJob(const std::string& jobID);
void updateJobStatus(const std::string& jobID);
void removeUser(const std::string& userID);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID);
@@ -61,6 +67,8 @@ public:
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID);
void configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications);
void configureNotifications(bool paymentNotifications, bool serviceNotifications);
void loadSystemData();
void saveSystemData();
void runSystemChecks();
};
@@ -1,3 +1,10 @@
/*
File: Observer.h
Description: Declares the Observer interface for handling notifications in the Vehicle Service Management System.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
class Notification;
@@ -6,5 +13,5 @@ class Observer
{
public:
virtual ~Observer() = default;
virtual void update(Notification* notification) = 0;
virtual void addNotification(Notification* notification) = 0;
};
@@ -1,6 +1,14 @@
/*
File: Subject.h
Description: Declares the Subject interface for managing user attachments and detachments in the Observer design pattern within the Vehicle Service Management System.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
class User;
class Notification;
@@ -1,46 +1,128 @@
/*
File: DataStore.cpp
Description: Implements the DataStore class which provides a centralized singleton repository
for managing system data in the Vehicle Service Management System.
Includes accessors for users, services, combo packages, service bookings,
job cards, inventory items, invoices, and payments.
Author: Trenser
Date: 19-May-2026
*/
#include "DataStore.h"
/*
Function: getInstance
Description: Provides a singleton instance of the DataStore class.
Parameters:
- None
Returns:
- Reference to the single DataStore instance.
*/
DataStore& DataStore::getInstance()
{
static DataStore dataStore;
return dataStore;
}
/*
Function: getUsers
Description: Retrieves the internal map of users.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, User*> containing all users.
*/
util::Map<std::string, User*>& DataStore::getUsers()
{
return m_users;
}
/*
Function: getServices
Description: Retrieves the internal map of services.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, Service*> containing all services.
*/
util::Map<std::string, Service*>& DataStore::getServices()
{
return m_services;
}
/*
Function: getComboPackages
Description: Retrieves the internal map of combo packages.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, ComboPackage*> containing all combo packages.
*/
util::Map<std::string, ComboPackage*>& DataStore::getComboPackages()
{
return m_comboPackages;
}
/*
Function: getServiceBookings
Description: Retrieves the internal map of service bookings.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, ServiceBooking*> containing all service bookings.
*/
util::Map<std::string, ServiceBooking*>& DataStore::getServiceBookings()
{
return m_serviceBookings;
}
/*
Function: getJobCards
Description: Retrieves the internal map of job cards.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, JobCard*> containing all job cards.
*/
util::Map<std::string, JobCard*>& DataStore::getJobCards()
{
return m_jobCards;
}
/*
Function: getInventoryItems
Description: Retrieves the internal map of inventory items.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, InventoryItem*> containing all inventory items.
*/
util::Map<std::string, InventoryItem*>& DataStore::getInventoryItems()
{
return m_inventoryItems;
}
/*
Function: getInvoices
Description: Retrieves the internal map of invoices.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, Invoice*> containing all invoices.
*/
util::Map<std::string, Invoice*>& DataStore::getInvoices()
{
return m_invoices;
}
/*
Function: getPayments
Description: Retrieves the internal map of payments.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, Payment*> containing all payments.
*/
util::Map<std::string, Payment*>& DataStore::getPayments()
{
return m_payments;
@@ -1,5 +1,11 @@
#pragma once
/*
File: DataStore.h
Description: Declares the DataStore singleton class responsible for managing collections of users, services, combo packages, service bookings, job cards, inventory items, invoices, and payments in the Vehicle Service Management System.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -1,65 +1,341 @@
/*
File: ComboPackage.cpp
Description: Implements the ComboPackage class which represents a bundled set of services in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for package details such as ID, name, discount percentage, state,
and associated services.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include <stdexcept>
#include "ComboPackage.h"
#include "Service.h"
#include "Factory.h"
#include "StringHelper.h"
int ComboPackage::m_uid = 0;
/*
Function: ComboPackage
Description: Default constructor that initializes a new combo package with a unique ID,
active state, and zero discount percentage.
Parameters:
- None
Returns:
- A new ComboPackage object.
*/
ComboPackage::ComboPackage()
: m_id("CMP" + std::to_string(++m_uid)),
m_status(util::State::ACTIVE),
m_discountPercentage(0.0) {}
/*
Function: ComboPackage
Description: Parameterized constructor that initializes a new combo package with a unique ID,
specified package name, discount percentage, active state, and associated services.
Parameters:
- packageName: Name of the combo package.
- discountPercentage: Discount percentage applied to the package.
- services: Map of services included in the package.
Returns:
- A new ComboPackage object.
*/
ComboPackage::ComboPackage(const std::string& packageName, double discountPercentage, const util::Map<std::string, Service*>& services)
: m_id("CMP" + std::to_string(++m_uid)),
m_packageName(packageName),
m_discountPercentage(discountPercentage),
m_status(util::State::ACTIVE),
m_services(services) {}
m_services(services)
{
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
Function: ComboPackage (parameterized constructor with ID)
Description: Initializes a combo package with an existing ID, name, discount percentage,
service IDs, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the package
- packageName: const std::string&, name of the package
- discountPercentage: double, discount percentage applied
- serviceIDs: const util::Vector<std::string>&, IDs of services included
- status: util::State, state of the package (ACTIVE/INACTIVE)
Returns:
- A new ComboPackage object
*/
ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status)
: m_id(id),
m_packageName(packageName),
m_discountPercentage(discountPercentage),
m_serviceIDs(serviceIDs),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the combo package.
Parameters:
- None
Returns:
- const std::string& representing the package ID.
*/
const std::string& ComboPackage::getId() const
{
return m_id;
}
/*
Function: getPackageName
Description: Retrieves the name of the combo package.
Parameters:
- None
Returns:
- const std::string& representing the package name.
*/
const std::string& ComboPackage::getPackageName() const
{
return m_packageName;
}
/*
Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the combo package.
Parameters:
- None
Returns:
- double representing the discount percentage.
*/
double ComboPackage::getDiscountPercentage() const
{
return m_discountPercentage;
}
/*
Function: getState
Description: Retrieves the current state (ACTIVE/INACTIVE) of the combo package.
Parameters:
- None
Returns:
- util::State representing the package state.
*/
util::State ComboPackage::getState() const
{
return m_status;
}
const util::Vector<std::string>& ComboPackage::getServiceIDs() const
{
return m_serviceIDs;
}
/*
Function: getServices
Description: Retrieves the map of services included in the combo package.
Parameters:
- None
Returns:
- const util::Map<std::string, Service*>& representing the services.
*/
const util::Map<std::string, Service*>& ComboPackage::getServices() const
{
return m_services;
}
/*
Function: setId
Description: Sets the unique ID of the combo package.
Parameters:
- id: New ID string.
Returns:
- void
*/
void ComboPackage::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setPackageName
Description: Sets the name of the combo package.
Parameters:
- packageName: New package name string.
Returns:
- void
*/
void ComboPackage::setPackageName(const std::string& packageName)
{
m_packageName = packageName;
}
/*
Function: setDiscountPercentage
Description: Sets the discount percentage for the combo package.
Parameters:
- discountPercentage: New discount percentage value.
Returns:
- void
*/
void ComboPackage::setDiscountPercentage(double discountPercentage)
{
m_discountPercentage = discountPercentage;
}
/*
Function: setServices
Description: Sets the services included in the combo package.
Parameters:
- services: Map of services to be associated with the package.
Returns:
- void
*/
void ComboPackage::setServices(const util::Map<std::string, Service*>& services)
{
m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
Function: setState
Description: Sets the state (ACTIVE/INACTIVE) of the combo package.
Parameters:
- status: New state value.
Returns:
- void
*/
void ComboPackage::setState(util::State status)
{
m_status = status;
}
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
/*
Function: serialize
Description: Serializes the combo package into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized combo package record
*/
std::string ComboPackage::serialize() const
{
std::ostringstream serializedComboPackage;
serializedComboPackage << m_id << ','
<< m_packageName << ','
<< m_discountPercentage << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< util::getStateString(m_status);
return serializedComboPackage.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ComboPackage object.
Parameters:
- record: const std::string&, serialized combo package record
Returns:
- ComboPackage*: Pointer to the deserialized ComboPackage object
Throws:
- std::runtime_error if data is invalid
*/
ComboPackage* ComboPackage::deserialize(const std::string& record)
{
std::string id, packageName;
std::string discountPercentageString, serviceIDsString, statusString;
double discountPercentage;
std::istringstream serializedComboPackage(record);
getline(serializedComboPackage, id, ',');
getline(serializedComboPackage, packageName, ',');
getline(serializedComboPackage, discountPercentageString, ',');
getline(serializedComboPackage, serviceIDsString, ',');
getline(serializedComboPackage, statusString, ',');
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid combo package data");
}
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
util::State status = util::getState(statusString);
return Factory::getObject<ComboPackage>(
id,
packageName,
discountPercentage,
serviceIDs,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for combo package serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PackageName,DiscountPercentage,ServiceIDs,Status")
*/
std::string ComboPackage::getHeaders()
{
return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
}
@@ -1,6 +1,14 @@
/*
File: ComboPackage.h
Description: Declares the ComboPackage class which represents a service package with a unique ID, package name, discount percentage, associated services, and status in the Vehicle Service Management System.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class Service;
@@ -12,14 +20,17 @@ private:
std::string m_id;
std::string m_packageName;
double m_discountPercentage;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services;
util::State m_status;
public:
ComboPackage();
ComboPackage(const std::string& packageName, double discountPercentage, const util::Map<std::string, Service*>& services);
ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status);
const std::string& getId() const;
const std::string& getPackageName() const;
double getDiscountPercentage() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const;
util::State getState() const;
void setId(const std::string& id);
@@ -27,4 +38,7 @@ public:
void setDiscountPercentage(double discountPercentage);
void setServices(const util::Map<std::string, Service*>& services);
void setState(util::State status);
std::string serialize() const;
static ComboPackage* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,13 +1,45 @@
/*
File: InventoryItem.cpp
Description: Implements the InventoryItem class which represents an inventory item in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for item details such as ID, part name, quantity, price, and state.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include <stdexcept>
#include "Factory.h"
#include "StringHelper.h"
#include "InventoryItem.h"
int InventoryItem::m_uid = 0;
/*
Function: InventoryItem
Description: Default constructor that initializes a new inventory item with a unique ID,
active state, zero quantity, and zero price.
Parameters:
- None
Returns:
- A new InventoryItem object.
*/
InventoryItem::InventoryItem()
: m_id("IIM" + std::to_string(++m_uid)),
m_quantity(0),
m_status(util::State::ACTIVE),
m_price(0.0) {}
/*
Function: InventoryItem
Description: Parameterized constructor that initializes a new inventory item with a unique ID,
specified part name, quantity, price, and active state.
Parameters:
- partName: Name of the inventory item.
- quantity: Initial quantity of the item.
- price: Price of the item.
Returns:
- A new InventoryItem object.
*/
InventoryItem::InventoryItem(const std::string& partName, int quantity, double price)
: m_id("IIM" + std::to_string(++m_uid)),
m_partName(partName),
@@ -15,52 +47,232 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_status(util::State::ACTIVE),
m_price(price) {}
/*
Function: InventoryItem (parameterized constructor with ID)
Description: Initializes an inventory item with an existing ID, part name, quantity,
price, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the item
- partName: const std::string&, name of the part
- quantity: int, quantity of the part
- price: double, price of the part
- status: util::State, state of the item (ACTIVE/INACTIVE)
Returns:
- A new InventoryItem object
*/
InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status)
: m_id(id),
m_partName(partName),
m_quantity(quantity),
m_status(status),
m_price(price)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the inventory item.
Parameters:
- None
Returns:
- const std::string& representing the item ID.
*/
const std::string& InventoryItem::getId() const
{
return m_id;
}
/*
Function: getPartName
Description: Retrieves the part name of the inventory item.
Parameters:
- None
Returns:
- const std::string& representing the part name.
*/
const std::string& InventoryItem::getPartName() const
{
return m_partName;
}
/*
Function: getQuantity
Description: Retrieves the current quantity of the inventory item.
Parameters:
- None
Returns:
- int representing the quantity.
*/
int InventoryItem::getQuantity() const
{
return m_quantity;
}
/*
Function: getPrice
Description: Retrieves the price of the inventory item.
Parameters:
- None
Returns:
- double representing the price.
*/
double InventoryItem::getPrice() const
{
return m_price;
}
/*
Function: getState
Description: Retrieves the current state (ACTIVE/INACTIVE) of the inventory item.
Parameters:
- None
Returns:
- util::State representing the item state.
*/
util::State InventoryItem::getState() const
{
return m_status;
}
/*
Function: setId
Description: Sets the unique ID of the inventory item.
Parameters:
- id: New ID string.
Returns:
- void
*/
void InventoryItem::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setPartName
Description: Sets the part name of the inventory item.
Parameters:
- partName: New part name string.
Returns:
- void
*/
void InventoryItem::setPartName(const std::string& partName)
{
m_partName = partName;
}
/*
Function: setQuantity
Description: Sets the quantity of the inventory item.
Parameters:
- quantity: New quantity value.
Returns:
- void
*/
void InventoryItem::setQuantity(int quantity)
{
m_quantity = quantity;
}
/*
Function: setPrice
Description: Sets the price of the inventory item.
Parameters:
- price: New price value.
Returns:
- void
*/
void InventoryItem::setPrice(double price)
{
m_price = price;
}
/*
Function: setState
Description: Sets the state (ACTIVE/INACTIVE) of the inventory item.
Parameters:
- status: New state value.
Returns:
- void
*/
void InventoryItem::setState(util::State status)
{
m_status = status;
}
/*
Function: serialize
Description: Serializes the inventory item into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized inventory item record
*/
std::string InventoryItem::serialize() const
{
std::ostringstream serializedInventoryItem;
serializedInventoryItem << m_id << ','
<< m_partName << ','
<< m_quantity << ','
<< m_price << ','
<< util::getStateString(m_status);
return serializedInventoryItem.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an InventoryItem object.
Parameters:
- record: const std::string&, serialized inventory item record
Returns:
- InventoryItem*: Pointer to the deserialized InventoryItem object
Throws:
- std::runtime_error if data is invalid
*/
InventoryItem* InventoryItem::deserialize(const std::string& record)
{
std::string id, partName;
std::string quantityString, priceString, statusString;
int quantity;
double price;
std::istringstream serializedInventoryItem(record);
getline(serializedInventoryItem, id, ',');
getline(serializedInventoryItem, partName, ',');
getline(serializedInventoryItem, quantityString, ',');
getline(serializedInventoryItem, priceString, ',');
getline(serializedInventoryItem, statusString, ',');
try
{
quantity = std::stoi(quantityString);
price = std::stod(priceString);
}
catch (...)
{
throw std::runtime_error("Invalid inventory item data");
}
util::State status = util::getState(statusString);
return Factory::getObject<InventoryItem>(
id,
partName,
quantity,
price,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for inventory item serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PartName,Quantity,Price,Status")
*/
std::string InventoryItem::getHeaders()
{
return "ID,PartName,Quantity,Price,Status";
}
@@ -1,3 +1,12 @@
/*
File: InventoryItem.h
Description: Declares the InventoryItem class which represents parts in the Vehicle Service Management System.
Each item has a unique ID, part name, quantity, price, and status.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Enums.h"
@@ -14,6 +23,7 @@ private:
public:
InventoryItem();
InventoryItem(const std::string& partName, int quantity, double price);
InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status);
const std::string& getId() const;
const std::string& getPartName() const;
int getQuantity() const;
@@ -24,4 +34,7 @@ public:
void setQuantity(int quantity);
void setPrice(double price);
void setState(util::State status);
std::string serialize() const;
static InventoryItem* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,7 +1,31 @@
/*
File: Invoice.cpp
Description: Implements the Invoice class which represents an invoice in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for invoice details such as ID, booking, costs,
discount percentage, total amount, payment details, and status.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include <stdexcept>
#include "Invoice.h"
#include "Factory.h"
#include "InventoryItem.h"
#include "StringHelper.h"
int Invoice::m_uid = 0;
/*
Function: Invoice
Description: Default constructor that initializes a new invoice with a unique ID,
null booking, zero costs, zero discount, zero total amount,
and default payment method and status.
Parameters:
- None
Returns:
- A new Invoice object.
*/
Invoice::Invoice()
: m_id("INV" + std::to_string(++m_uid)),
m_booking(nullptr),
@@ -12,12 +36,30 @@ Invoice::Invoice()
m_paymentMethod(util::PaymentMode()),
m_status(util::PaymentStatus()) {}
/*
Function: Invoice
Description: Parameterized constructor that initializes a new invoice with a unique ID and specified details.
Parameters:
- bookingId: ID of the associated service booking.
- booking: Pointer to the ServiceBooking object.
- invoiceDate: Timestamp of when the invoice was created.
- laborCost: Cost of labor for the service.
- parts: Map of inventory items used in the service.
- partsCost: Total cost of parts.
- discountPercentage: Discount applied to the invoice.
- totalAmount: Final total amount after discount.
- paymentDate: Timestamp of when payment was made.
- paymentMethod: Payment mode (ONLINE/OFFLINE).
- status: Payment status (PENDING/COMPLETED).
Returns:
- A new Invoice object.
*/
Invoice::Invoice(
const std::string& bookingId,
ServiceBooking* booking,
const util::Timestamp& invoiceDate,
double laborCost, const util::Map<int,
InventoryItem*>& parts,
double laborCost,
const util::Map<std::string, InventoryItem*>& parts,
double partsCost,
double discountPercentage,
double totalAmount,
@@ -36,124 +78,495 @@ Invoice::Invoice(
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
m_status(status) {}
m_status(status)
{
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
}
Invoice::Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_invoiceDate(invoiceDate),
m_partIDs(partIDs),
m_laborCost(laborCost),
m_partsCost(partsCost),
m_discountPercentage(discountPercentage),
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the invoice.
Returns:
- const std::string& representing the invoice ID.
*/
const std::string& Invoice::getId() const
{
return m_id;
}
/*
Function: getBookingId
Description: Retrieves the booking ID associated with the invoice.
Returns:
- const std::string& representing the booking ID.
*/
const std::string& Invoice::getBookingId() const
{
return m_bookingId;
}
/*
Function: getBooking
Description: Retrieves the pointer to the associated ServiceBooking.
Returns:
- ServiceBooking* representing the booking.
*/
ServiceBooking* Invoice::getBooking() const
{
return m_booking;
}
/*
Function: getInvoiceDate
Description: Retrieves the timestamp of the invoice creation date.
Returns:
- const util::Timestamp& representing the invoice date.
*/
const util::Timestamp& Invoice::getInvoiceDate() const
{
return m_invoiceDate;
}
/*
Function: getLaborCost
Description: Retrieves the labor cost associated with the invoice.
Returns:
- double representing the labor cost.
*/
double Invoice::getLaborCost() const
{
return m_laborCost;
}
const util::Map<int, InventoryItem*>& Invoice::getParts() const
/*
Function: getPartIDs
Description: Retrieves the IDs of parts used in the invoice.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Part IDs
*/
const util::Vector<std::string>& Invoice::getPartIDs() const
{
return m_partIDs;
}
/*
Function: getParts
Description: Retrieves the map of inventory items used in the service.
Returns:
- const util::Map<int, InventoryItem*>& representing the parts.
*/
const util::Map<std::string, InventoryItem*>& Invoice::getParts() const
{
return m_parts;
}
/*
Function: getPartsCost
Description: Retrieves the total cost of parts used in the service.
Returns:
- double representing the parts cost.
*/
double Invoice::getPartsCost() const
{
return m_partsCost;
}
/*
Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the invoice.
Returns:
- double representing the discount percentage.
*/
double Invoice::getDiscountPercentage() const
{
return m_discountPercentage;
}
/*
Function: getTotalAmount
Description: Retrieves the total amount of the invoice after discount.
Returns:
- double representing the total amount.
*/
double Invoice::getTotalAmount() const
{
return m_totalAmount;
}
/*
Function: getPaymentDate
Description: Retrieves the timestamp of the payment date.
Returns:
- const util::Timestamp& representing the payment date.
*/
const util::Timestamp& Invoice::getPaymentDate() const
{
return m_paymentDate;
}
/*
Function: getPaymentMethod
Description: Retrieves the payment mode used for the invoice.
Returns:
- util::PaymentMode representing the payment method.
*/
util::PaymentMode Invoice::getPaymentMethod() const
{
return m_paymentMethod;
}
/*
Function: getStatus
Description: Retrieves the payment status of the invoice.
Returns:
- util::PaymentStatus representing the payment status.
*/
util::PaymentStatus Invoice::getStatus() const
{
return m_status;
}
/*
Function: setId
Description: Sets the unique ID of the invoice.
Parameters:
- id: New invoice ID string.
Returns:
- void
*/
void Invoice::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setBookingId
Description: Sets the booking ID associated with the invoice.
Parameters:
- bookingId: New booking ID string.
Returns:
- void
*/
void Invoice::setBookingId(const std::string& bookingId)
{
m_bookingId = bookingId;
}
/*
Function: setBooking
Description: Sets the associated ServiceBooking pointer.
Parameters:
- booking: Pointer to the ServiceBooking object.
Returns:
- void
*/
void Invoice::setBooking(ServiceBooking* booking)
{
m_booking = booking;
}
/*
Function: setInvoiceDate
Description: Sets the invoice creation date.
Parameters:
- invoiceDate: New timestamp for the invoice date.
Returns:
- void
*/
void Invoice::setInvoiceDate(const util::Timestamp& invoiceDate)
{
m_invoiceDate = invoiceDate;
}
/*
Function: setLaborCost
Description: Sets the labor cost for the invoice.
Parameters:
- laborCost: New labor cost value.
Returns:
- void
*/
void Invoice::setLaborCost(double laborCost)
{
m_laborCost = laborCost;
}
void Invoice::setParts(const util::Map<int, InventoryItem*>& parts)
/*
Function: setParts
Description: Sets the inventory items used in the service.
Parameters:
- parts: Map of inventory items.
Returns:
- void
*/
void Invoice::setParts(const util::Map<std::string, InventoryItem*>& parts)
{
m_parts = parts;
m_partIDs.clear();
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
}
/*
Function: setPartsCost
Description: Sets the total cost of parts used in the service.
Parameters:
- partsCost: New parts cost value.
Returns:
- void
*/
void Invoice::setPartsCost(double partsCost)
{
m_partsCost = partsCost;
}
/*
Function: setDiscountPercentage
Description: Sets the discount percentage applied to the invoice.
Parameters:
- discountPercentage: New discount percentage value.
Returns:
- void
*/
void Invoice::setDiscountPercentage(double discountPercentage)
{
m_discountPercentage = discountPercentage;
}
/*
Function: setTotalAmount
Description: Sets the total amount of the invoice.
Parameters:
- totalAmount: New total amount value.
Returns:
- void
*/
void Invoice::setTotalAmount(double totalAmount)
{
m_totalAmount = totalAmount;
}
/*
Function: setPaymentDate
Description: Sets the payment date for the invoice.
Parameters:
- paymentDate: New timestamp for the payment date.
Returns:
- void
*/
void Invoice::setPaymentDate(const util::Timestamp& paymentDate)
{
m_paymentDate = paymentDate;
}
/*
Function: setPaymentMethod
Description: Sets the payment mode for the invoice.
Parameters:
- paymentMethod: New payment mode value.
Returns:
- void
*/
void Invoice::setPaymentMethod(util::PaymentMode paymentMethod)
{
m_paymentMethod = paymentMethod;
}
/*
Function: setStatus
Description: Sets the payment status of the invoice.
Parameters:
- status: New payment status value.
Returns:
- void
*/
void Invoice::setStatus(util::PaymentStatus status)
{
m_status = status;
}
/*
Function: getPartIDsAsString (static helper)
Description: Converts a vector of part IDs into a single string separated by '|'.
Parameters:
- partIDs: const util::Vector<std::string>&, vector of part IDs
Returns:
- std::string: Concatenated part IDs string
*/
static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
{
int numberOfParts = partIDs.getSize();
std::string partIDsString;
for (int index = 0; index < numberOfParts; index++)
{
partIDsString += partIDs[index];
if (index < numberOfParts - 1)
{
partIDsString += '|';
}
}
return partIDsString;
}
/*
Function: getPartIDsAsVector (static helper)
Description: Converts a string of part IDs separated by '|' into a vector.
Parameters:
- partIDsString: const std::string&, concatenated part IDs string
Returns:
- util::Vector<std::string>: Vector of part IDs
*/
static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString)
{
util::Vector<std::string> partIDs;
std::string partID;
std::istringstream serializedPartIDs(partIDsString);
while (getline(serializedPartIDs, partID, '|'))
{
partIDs.push_back(partID);
}
return partIDs;
}
/*
Function: serialize
Description: Serializes the invoice into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized invoice record
*/
std::string Invoice::serialize() const
{
std::ostringstream serializedInvoice;
serializedInvoice << m_id << ','
<< m_bookingId << ','
<< m_invoiceDate.toString() << ','
<< m_laborCost << ','
<< getPartIDsAsString(m_partIDs) << ','
<< m_partsCost << ','
<< m_discountPercentage << ','
<< m_totalAmount << ','
<< m_paymentDate.toString() << ','
<< util::getPaymentModeString(m_paymentMethod) << ','
<< util::getPaymentStatusString(m_status);
return serializedInvoice.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an Invoice object.
Parameters:
- record: const std::string&, serialized invoice record
Returns:
- Invoice*: Pointer to the deserialized Invoice object
Throws:
- std::runtime_error if data is invalid
*/
Invoice* Invoice::deserialize(const std::string& record)
{
std::string id, bookingId;
std::string invoiceDateString, laborCostString, partIDsString;
std::string partsCostString, discountPercentageString, totalAmountString;
std::string paymentDateString, paymentMethodString, statusString;
double laborCost, partsCost, discountPercentage, totalAmount;
std::istringstream serializedInvoice(record);
getline(serializedInvoice, id, ',');
getline(serializedInvoice, bookingId, ',');
getline(serializedInvoice, invoiceDateString, ',');
getline(serializedInvoice, laborCostString, ',');
getline(serializedInvoice, partIDsString, ',');
getline(serializedInvoice, partsCostString, ',');
getline(serializedInvoice, discountPercentageString, ',');
getline(serializedInvoice, totalAmountString, ',');
getline(serializedInvoice, paymentDateString, ',');
getline(serializedInvoice, paymentMethodString, ',');
getline(serializedInvoice, statusString, ',');
util::Timestamp invoiceDate;
util::Timestamp paymentDate;
try
{
invoiceDate = util::Timestamp::fromString(invoiceDateString);
paymentDate = util::Timestamp::fromString(paymentDateString);
laborCost = std::stod(laborCostString);
partsCost = std::stod(partsCostString);
discountPercentage = std::stod(discountPercentageString);
totalAmount = std::stod(totalAmountString);
}
catch (...)
{
throw std::runtime_error("Invalid invoice data");
}
util::Vector<std::string> partIDs = getPartIDsAsVector(partIDsString);
util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString);
util::PaymentStatus status = util::getPaymentStatus(statusString);
return Factory::getObject<Invoice>(
id,
bookingId,
invoiceDate,
partIDs,
laborCost,
partsCost,
discountPercentage,
totalAmount,
paymentDate,
paymentMethod,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for invoice serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status")
*/
std::string Invoice::getHeaders()
{
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
}
@@ -1,6 +1,16 @@
/*
File: Invoice.h
Description: Declares the Invoice class which represents billing details for a service booking in the Vehicle Service Management System.
Each invoice includes booking information, labor cost, parts used, discount percentage, total amount, payment details, and status.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Timestamp.h"
#include "Enums.h"
@@ -16,22 +26,22 @@ private:
ServiceBooking* m_booking;
util::Timestamp m_invoiceDate;
double m_laborCost;
util::Map<int, InventoryItem*> m_parts;
util::Vector<std::string> m_partIDs;
util::Map<std::string, InventoryItem*> m_parts;
double m_partsCost;
double m_discountPercentage;
double m_totalAmount;
util::Timestamp m_paymentDate;
util::PaymentMode m_paymentMethod;
util::PaymentStatus m_status;
public:
Invoice();
Invoice(
const std::string& bookingId,
ServiceBooking* booking,
const util::Timestamp& invoiceDate,
double laborCost, const util::Map<int,
InventoryItem*>& parts,
double laborCost,
const util::Map<std::string,InventoryItem*>& parts,
double partsCost,
double discountPercentage,
double totalAmount,
@@ -39,12 +49,26 @@ public:
util::PaymentMode paymentMethod,
util::PaymentStatus status
);
Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
);
const std::string& getId() const;
const std::string& getBookingId() const;
ServiceBooking* getBooking() const;
const util::Timestamp& getInvoiceDate() const;
double getLaborCost() const;
const util::Map<int, InventoryItem*>& getParts() const;
const util::Vector<std::string>& getPartIDs() const;
const util::Map<std::string, InventoryItem*>& getParts() const;
double getPartsCost() const;
double getDiscountPercentage() const;
double getTotalAmount() const;
@@ -56,11 +80,14 @@ public:
void setBooking(ServiceBooking* booking);
void setInvoiceDate(const util::Timestamp& invoiceDate);
void setLaborCost(double laborCost);
void setParts(const util::Map<int, InventoryItem*>& parts);
void setParts(const util::Map<std::string, InventoryItem*>& parts);
void setPartsCost(double partsCost);
void setDiscountPercentage(double discountPercentage);
void setTotalAmount(double totalAmount);
void setPaymentDate(const util::Timestamp& paymentDate);
void setPaymentMethod(util::PaymentMode paymentMethod);
void setStatus(util::PaymentStatus status);
std::string serialize() const;
static Invoice* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,14 +1,51 @@
/*
File: JobCard.cpp
Description: Implementation file containing the method definitions of the
JobCard class, including constructors, getters, and setters
for job card attributes.
Author: Trenser
Date:19-May-2026
*/
#include <sstream>
#include <stdexcept>
#include "JobCard.h"
#include "Factory.h"
#include "StringHelper.h"
#include "Enums.h"
int JobCard::m_uid = 0;
/*
Function: JobCard
Description: Default constructor that initializes a new job card with
a unique ID and default values.
Parameter: None
Return type: Constructor
*/
JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)),
m_booking(nullptr),
m_service(nullptr),
m_technician(nullptr),
m_status(ServiceJobStatus()) {}
m_status(util::ServiceJobStatus()) {}
/*
Function: JobCard
Description: Parameterized constructor that initializes a new job card with a unique ID and specified details.
Parameters:
- bookingId: ID of the associated service booking.
- booking: Pointer to the ServiceBooking object.
- service: Pointer to the Service object.
- serviceId: ID of the associated service.
- technicianId: ID of the assigned technician.
- technician: Pointer to the User object representing the technician.
- assignedDate: Timestamp of when the job was assigned.
- status: Current status of the job (STARTED/COMPLETED).
- completionDate: Timestamp of when the job was completed.
Returns:
- A new JobCard object.
*/
JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking,
Service* service,
@@ -16,7 +53,7 @@ JobCard::JobCard(const std::string& bookingId,
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
ServiceJobStatus status,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id("JC" + std::to_string(++m_uid)),
@@ -30,102 +67,363 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status),
m_completionDate(completionDate) {}
/*
Function: JobCard (parameterized constructor with ID)
Description: Initializes a job card with an existing ID, booking ID, service ID,
technician ID, assignment date, completion date, and status.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique job card ID
- bookingId: const std::string&, ID of the booking
- serviceId: const std::string&, ID of the service
- technicianId: const std::string&, ID of the technician
- assignedDate: const util::Timestamp&, date of assignment
- status: util::ServiceJobStatus, job status
- completionDate: const util::Timestamp&, date of completion
Returns:
- A new JobCard object
*/
JobCard::JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_service(nullptr),
m_serviceId(serviceId),
m_technicianId(technicianId),
m_technician(nullptr),
m_assignedDate(assignedDate),
m_status(status),
m_completionDate(completionDate)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the job card.
Returns:
- const std::string& representing the job card ID.
*/
const std::string& JobCard::getId() const
{
return m_id;
}
/*
Function: getBookingId
Description: Retrieves the booking ID associated with the job card.
Returns:
- const std::string& representing the booking ID.
*/
const std::string& JobCard::getBookingId() const
{
return m_bookingId;
}
/*
Function: getBooking
Description: Retrieves the pointer to the associated ServiceBooking.
Returns:
- ServiceBooking* representing the booking.
*/
ServiceBooking* JobCard::getBooking() const
{
return m_booking;
}
/*
Function: getService
Description: Retrieves the pointer to the associated Service.
Returns:
- Service* representing the service.
*/
Service* JobCard::getService() const
{
return m_service;
}
/*
Function: getServiceId
Description: Retrieves the service ID associated with the job card.
Returns:
- const std::string& representing the service ID.
*/
const std::string& JobCard::getServiceId() const
{
return m_serviceId;
}
/*
Function: getTechnicianId
Description: Retrieves the technician ID associated with the job card.
Returns:
- const std::string& representing the technician ID.
*/
const std::string& JobCard::getTechnicianId() const
{
return m_technicianId;
}
/*
Function: getTechnician
Description: Retrieves the pointer to the assigned technician.
Returns:
- User* representing the technician.
*/
User* JobCard::getTechnician() const
{
return m_technician;
}
/*
Function: getAssignedDate
Description: Retrieves the timestamp of when the job was assigned.
Returns:
- const util::Timestamp& representing the assigned date.
*/
const util::Timestamp& JobCard::getAssignedDate() const
{
return m_assignedDate;
}
ServiceJobStatus JobCard::getStatus() const
/*
Function: getStatus
Description: Retrieves the current status of the job.
Returns:
- ServiceJobStatus representing the job status.
*/
util::ServiceJobStatus JobCard::getStatus() const
{
return m_status;
}
/*
Function: getCompletionDate
Description: Retrieves the timestamp of when the job was completed.
Returns:
- const util::Timestamp& representing the completion date.
*/
const util::Timestamp& JobCard::getCompletionDate() const
{
return m_completionDate;
}
/*
Function: setId
Description: Sets the unique ID of the job card.
Parameters:
- id: New job card ID string.
Returns:
- void
*/
void JobCard::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setBookingId
Description: Sets the booking ID associated with the job card.
Parameters:
- bookingId: New booking ID string.
Returns:
- void
*/
void JobCard::setBookingId(const std::string& bookingId)
{
m_bookingId = bookingId;
}
/*
Function: setBooking
Description: Sets the associated ServiceBooking pointer.
Parameters:
- booking: Pointer to the ServiceBooking object.
Returns:
- void
*/
void JobCard::setBooking(ServiceBooking* booking)
{
m_booking = booking;
}
/*
Function: setService
Description: Sets the associated Service pointer.
Parameters:
- service: Pointer to the Service object.
Returns:
- void
*/
void JobCard::setService(Service* service)
{
m_service = service;
}
/*
Function: setServiceId
Description: Sets the service ID associated with the job card.
Parameters:
- serviceId: New service ID string.
Returns:
- void
*/
void JobCard::setServiceId(const std::string& serviceId)
{
m_serviceId = serviceId;
}
/*
Function: setTechnicianId
Description: Sets the technician ID associated with the job card.
Parameters:
- technicianId: New technician ID string.
Returns:
- void
*/
void JobCard::setTechnicianId(const std::string& technicianId)
{
m_technicianId = technicianId;
}
/*
Function: setTechnician
Description: Sets the pointer to the assigned technician.
Parameters:
- technician: Pointer to the User object.
Returns:
- void
*/
void JobCard::setTechnician(User* technician)
{
m_technician = technician;
}
/*
Function: setAssignedDate
Description: Sets the timestamp of when the job was assigned.
Parameters:
- assignedDate: New timestamp for the assigned date.
Returns:
- void
*/
void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
{
m_assignedDate = assignedDate;
}
void JobCard::setStatus(ServiceJobStatus status)
/*
Function: setStatus
Description: Sets the current status of the job.
Parameters:
- status: New job status value.
Returns:
- void
*/
void JobCard::setStatus(util::ServiceJobStatus status)
{
m_status = status;
}
/*
Function: setCompletionDate
Description: Sets the timestamp of when the job was completed.
Parameters:
- completionDate: New timestamp for the completion date.
Returns:
- void
*/
void JobCard::setCompletionDate(const util::Timestamp& completionDate)
{
m_completionDate = completionDate;
}
/*
Function: serialize
Description: Serializes the job card into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized job card record
*/
std::string JobCard::serialize() const
{
std::ostringstream serializedJobCard;
serializedJobCard << m_id << ','
<< m_bookingId << ','
<< m_serviceId << ','
<< m_technicianId << ','
<< m_assignedDate.toString() << ','
<< util::getServiceJobStatusString(m_status) << ','
<< m_completionDate.toString();
return serializedJobCard.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a JobCard object.
Parameters:
- record: const std::string&, serialized job card record
Returns:
- JobCard*: Pointer to the deserialized JobCard object
Throws:
- std::runtime_error if timestamp parsing fails
*/
JobCard* JobCard::deserialize(const std::string& record)
{
std::string id, bookingId, serviceId, technicianId;
std::string assignedDateString, statusString, completionDateString;
std::istringstream serializedJobCard(record);
getline(serializedJobCard, id, ',');
getline(serializedJobCard, bookingId, ',');
getline(serializedJobCard, serviceId, ',');
getline(serializedJobCard, technicianId, ',');
getline(serializedJobCard, assignedDateString, ',');
getline(serializedJobCard, statusString, ',');
getline(serializedJobCard, completionDateString, ',');
util::Timestamp assignedDate;
util::Timestamp completionDate;
try
{
assignedDate = util::Timestamp::fromString(assignedDateString);
completionDate = util::Timestamp::fromString(completionDateString);
}
catch (...)
{
throw std::runtime_error("Invalid timestamp");
}
util::ServiceJobStatus status = util::getServiceJobStatus(statusString);
return Factory::getObject<JobCard>(
id,
bookingId,
serviceId,
technicianId,
assignedDate,
status,
completionDate
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for job card serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate")
*/
std::string JobCard::getHeaders()
{
return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
}
@@ -1,13 +1,21 @@
/*
File: JobCard.h
Description: Header file declaring the JobCard class, which represents
a service job card containing booking, service, technician,
and status details.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Enums.h"
#include "Timestamp.h"
class ServiceBooking;
class Service;
class User;
enum class ServiceJobStatus : int;
class JobCard
{
private:
@@ -20,9 +28,8 @@ private:
std::string m_technicianId;
User* m_technician;
util::Timestamp m_assignedDate;
ServiceJobStatus m_status;
util::ServiceJobStatus m_status;
util::Timestamp m_completionDate;
public:
JobCard();
JobCard(const std::string& bookingId,
@@ -32,7 +39,15 @@ public:
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
ServiceJobStatus status,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
);
JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
);
const std::string& getId() const;
@@ -43,7 +58,7 @@ public:
const std::string& getTechnicianId() const;
User* getTechnician() const;
const util::Timestamp& getAssignedDate() const;
ServiceJobStatus getStatus() const;
util::ServiceJobStatus getStatus() const;
const util::Timestamp& getCompletionDate() const;
void setId(const std::string& id);
void setBookingId(const std::string& bookingId);
@@ -53,6 +68,9 @@ public:
void setTechnicianId(const std::string& technicianId);
void setTechnician(User* technician);
void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(ServiceJobStatus status);
void setStatus(util::ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate);
std::string serialize() const;
static JobCard* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,11 +1,42 @@
/*
File: Notification.cpp
Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for notification details such as ID, recipient, title, message, and timestamp.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include "Notification.h"
#include "StringHelper.h"
#include "Factory.h"
int Notification::m_uid = 0;
/*
Function: Notification
Description: Default constructor that initializes a new notification with a unique ID and null recipient.
Parameters:
- None
Returns:
- A new Notification object.
*/
Notification::Notification()
: m_id("NOT" + std::to_string(++m_uid)),
m_recipient(nullptr) {}
/*
Function: Notification
Description: Parameterized constructor that initializes a new notification with a unique ID and specified details.
Parameters:
- recipientUserId: ID of the recipient user.
- recipient: Pointer to the User object representing the recipient.
- title: Title of the notification.
- message: Message content of the notification.
- createdAt: Timestamp of when the notification was created.
Returns:
- A new Notification object.
*/
Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id("NOT" + std::to_string(++m_uid)),
m_recipientUserId(recipientUserId),
@@ -14,62 +45,243 @@ Notification::Notification(const std::string& recipientUserId, User* recipient,
m_message(message),
m_createdAt(createdAt) {}
/*
Function: Notification (parameterized constructor with ID)
Description: Initializes a notification with an existing ID, recipient details,
title, message, and creation timestamp. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique notification ID
- recipientUserId: const std::string&, ID of the recipient user
- title: const std::string&, notification title
- message: const std::string&, notification message
- createdAt: const util::Timestamp&, timestamp of creation
Returns:
- A new Notification object
*/
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id(id),
m_recipientUserId(recipientUserId),
m_recipient(nullptr),
m_title(title),
m_message(message),
m_createdAt(createdAt)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the notification.
Returns:
- const std::string& representing the notification ID.
*/
const std::string& Notification::getId() const
{
return m_id;
}
/*
Function: getRecipientUserId
Description: Retrieves the recipient user ID associated with the notification.
Returns:
- const std::string& representing the recipient user ID.
*/
const std::string& Notification::getRecipientUserId() const
{
return m_recipientUserId;
}
/*
Function: getRecipient
Description: Retrieves the pointer to the recipient user.
Returns:
- User* representing the recipient.
*/
User* Notification::getRecipient() const
{
return m_recipient;
}
/*
Function: getTitle
Description: Retrieves the title of the notification.
Returns:
- const std::string& representing the notification title.
*/
const std::string& Notification::getTitle() const
{
return m_title;
}
/*
Function: getMessage
Description: Retrieves the message content of the notification.
Returns:
- const std::string& representing the notification message.
*/
const std::string& Notification::getMessage() const
{
return m_message;
}
/*
Function: getCreatedAt
Description: Retrieves the timestamp of when the notification was created.
Returns:
- const util::Timestamp& representing the creation timestamp.
*/
const util::Timestamp& Notification::getCreatedAt() const
{
return m_createdAt;
}
/*
Function: setId
Description: Sets the unique ID of the notification.
Parameters:
- id: New notification ID string.
Returns:
- void
*/
void Notification::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setRecipientUserId
Description: Sets the recipient user ID for the notification.
Parameters:
- recipientUserId: New recipient user ID string.
Returns:
- void
*/
void Notification::setRecipientUserId(const std::string& recipientUserId)
{
m_recipientUserId = recipientUserId;
}
/*
Function: setRecipient
Description: Sets the recipient user pointer for the notification.
Parameters:
- recipient: Pointer to the User object.
Returns:
- void
*/
void Notification::setRecipient(User* recipient)
{
m_recipient = recipient;
}
/*
Function: setTitle
Description: Sets the title of the notification.
Parameters:
- title: New notification title string.
Returns:
- void
*/
void Notification::setTitle(const std::string& title)
{
m_title = title;
}
/*
Function: setMessage
Description: Sets the message content of the notification.
Parameters:
- message: New notification message string.
Returns:
- void
*/
void Notification::setMessage(const std::string& message)
{
m_message = message;
}
/*
Function: setCreatedAt
Description: Sets the timestamp of when the notification was created.
Parameters:
- createdAt: New timestamp value.
Returns:
- void
*/
void Notification::setCreatedAt(const util::Timestamp& createdAt)
{
m_createdAt = createdAt;
}
/*
Function: serialize
Description: Serializes the notification into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized notification record
*/
std::string Notification::serialize() const
{
std::ostringstream serializedNotification;
serializedNotification << m_id << ','
<< m_recipientUserId << ','
<< m_title << ','
<< m_message << ','
<< m_createdAt.toString();
return serializedNotification.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Notification object.
Parameters:
- record: const std::string&, serialized notification record
Returns:
- Notification*: Pointer to the deserialized Notification object
Throws:
- std::runtime_error if timestamp parsing fails
*/
Notification* Notification::deserialize(const std::string& record)
{
std::string id, recipientUserId, title, message, createdAtTimestampString;
std::istringstream serializedNotification(record);
getline(serializedNotification, id, ',');
getline(serializedNotification, recipientUserId, ',');
getline(serializedNotification, title, ',');
getline(serializedNotification, message, ',');
getline(serializedNotification, createdAtTimestampString, ',');
util::Timestamp createdAtTimestamp;
try
{
createdAtTimestamp = util::Timestamp::fromString(createdAtTimestampString);
}
catch (...)
{
throw std::runtime_error("Invalid createdAt timestamp");
}
return Factory::getObject<Notification>(
id,
recipientUserId,
title,
message,
createdAtTimestamp
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for notification serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,RecipientID,Title,Message,Timestamp")
*/
std::string Notification::getHeaders()
{
return "ID,RecipientID,Title,Message,Timestamp";
}
@@ -1,3 +1,11 @@
/*
File: Notification.h
Description: Declares the Notification class which represents system messages sent to users in the Vehicle Service Management System.
Each notification includes a unique ID, recipient details, title, message content, and timestamp of creation.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Timestamp.h"
@@ -17,6 +25,7 @@ private:
public:
Notification();
Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
const std::string& getId() const;
const std::string& getRecipientUserId() const;
User* getRecipient() const;
@@ -29,4 +38,7 @@ public:
void setTitle(const std::string& title);
void setMessage(const std::string& message);
void setCreatedAt(const util::Timestamp& createdAt);
std::string serialize() const;
static Notification* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,65 +1,337 @@
/*
File: Service.cpp
Description: Implements the Service class which represents a vehicle service in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for service details such as ID, name, required inventory items,
labor cost, and state.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include "Service.h"
#include "InventoryItem.h"
#include "StringHelper.h"
#include "Factory.h"
int Service::m_uid = 0;
/*
Function: Service
Description: Default constructor that initializes a new service with a unique ID,
active state, and zero labor cost.
Parameters:
- None
Returns:
- A new Service object.
*/
Service::Service()
: m_id("SRV" + std::to_string(++m_uid)),
m_status(util::State::ACTIVE),
m_laborCost(0.0) {}
/*
Function: Service
Description: Parameterized constructor that initializes a new service with a unique ID and specified details.
Parameters:
- name: Name of the service.
- requiredInventoryItems: Map of inventory items required for the service.
- laborCost: Labor cost associated with the service.
Returns:
- A new Service object.
*/
Service::Service(const std::string& name, const util::Map<std::string, InventoryItem*>& requiredInventoryItems, double laborCost)
: m_id("SRV" + std::to_string(++m_uid)),
m_name(name),
m_requiredInventoryItems(requiredInventoryItems),
m_status(util::State::ACTIVE),
m_laborCost(laborCost) {}
m_laborCost(laborCost)
{
int numberOfInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
}
/*
Function: Service (parameterized constructor with ID)
Description: Initializes a service with an existing ID, name, inventory item IDs,
labor cost, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique service ID
- name: const std::string&, name of the service
- requiredInventoryItemIDs: const util::Vector<std::string>&, IDs of required inventory items
- laborCost: double, labor cost of the service
- status: util::State, state of the service (ACTIVE/INACTIVE)
Returns:
- A new Service object
*/
Service::Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State status)
: m_id(id),
m_name(name),
m_requiredInventoryItemIDs(requiredInventoryItemIDs),
m_status(status),
m_laborCost(laborCost)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the service.
Returns:
- const std::string& representing the service ID.
*/
const std::string& Service::getId() const
{
return m_id;
}
/*
Function: getName
Description: Retrieves the name of the service.
Returns:
- const std::string& representing the service name.
*/
const std::string& Service::getName() const
{
return m_name;
}
/*
Function: getRequiredInventoryItemIDs
Description: Retrieves the IDs of required inventory items for the service.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Inventory item IDs
*/
const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const
{
return m_requiredInventoryItemIDs;
}
/*
Function: getRequiredInventoryItems
Description: Retrieves the map of inventory items required for the service.
Returns:
- const util::Map<std::string, InventoryItem*>& representing the required inventory items.
*/
const util::Map<std::string, InventoryItem*>& Service::getRequiredInventoryItems() const
{
return m_requiredInventoryItems;
}
/*
Function: getLaborCost
Description: Retrieves the labor cost associated with the service.
Returns:
- double representing the labor cost.
*/
double Service::getLaborCost() const
{
return m_laborCost;
}
/*
Function: getState
Description: Retrieves the current state (ACTIVE/INACTIVE) of the service.
Returns:
- util::State representing the service state.
*/
util::State Service::getState() const
{
return m_status;
}
/*
Function: setId
Description: Sets the unique ID of the service.
Parameters:
- id: New service ID string.
Returns:
- void
*/
void Service::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setName
Description: Sets the name of the service.
Parameters:
- name: New service name string.
Returns:
- void
*/
void Service::setName(const std::string& name)
{
m_name = name;
}
/*
Function: setRequiredInventoryItems
Description: Sets the inventory items required for the service.
Parameters:
- requiredInventoryItems: Map of inventory items.
Returns:
- void
*/
void Service::setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems)
{
m_requiredInventoryItems = requiredInventoryItems;
m_requiredInventoryItemIDs.clear();
int numberOfRequiredInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfRequiredInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
}
/*
Function: setLaborCost
Description: Sets the labor cost for the service.
Parameters:
- laborCost: New labor cost value.
Returns:
- void
*/
void Service::setLaborCost(double laborCost)
{
m_laborCost = laborCost;
}
/*
Function: setState
Description: Sets the state (ACTIVE/INACTIVE) of the service.
Parameters:
- status: New state value.
Returns:
- void
*/
void Service::setState(util::State status)
{
m_status = status;
}
/*
Function: getInventoryItemIDsAsString (static helper)
Description: Converts a vector of inventory item IDs into a single string separated by '|'.
Parameters:
- inventoryItemIds: const util::Vector<std::string>&, vector of inventory item IDs
Returns:
- std::string: Concatenated inventory item IDs string
*/
static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds)
{
int numberOfInventoryItems = inventoryItemIds.getSize();
std::string inventoryItemIDs;
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItemIDs += inventoryItemIds[index];
if (index < numberOfInventoryItems - 1)
{
inventoryItemIDs += '|';
}
}
return inventoryItemIDs;
}
/*
Function: getInventoryItemIDsAsVector (static helper)
Description: Converts a string of inventory item IDs separated by '|' into a vector.
Parameters:
- inventoryItemIDsString: const std::string&, concatenated inventory item IDs string
Returns:
- util::Vector<std::string>: Vector of inventory item IDs
*/
static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString)
{
util::Vector<std::string> inventoryItemIDs;
std::string inventoryItemID;
std::istringstream serializedInventoryItemIDs(inventoryItemIDsString);
while (getline(serializedInventoryItemIDs, inventoryItemID, '|'))
{
inventoryItemIDs.push_back(inventoryItemID);
}
return inventoryItemIDs;
}
/*
Function: serialize
Description: Serializes the service into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized service record
*/
std::string Service::serialize() const
{
std::ostringstream serializedService;
serializedService << m_id << ','
<< m_name << ','
<< getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ','
<< m_laborCost << ','
<< util::getStateString(m_status);
return serializedService.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Service object.
Parameters:
- record: const std::string&, serialized service record
Returns:
- Service*: Pointer to the deserialized Service object
Throws:
- std::runtime_error if labor cost parsing fails
*/
Service* Service::deserialize(const std::string& record)
{
std::string id, name;
std::string inventoryItemIDsString, laborCostString, statusString;
double laborCost;
std::istringstream serializedService(record);
getline(serializedService, id, ',');
getline(serializedService, name, ',');
getline(serializedService, inventoryItemIDsString, ',');
getline(serializedService, laborCostString, ',');
getline(serializedService, statusString, ',');
util::Vector<std::string> inventoryItemIDs = getInventoryItemIDsAsVector(inventoryItemIDsString);
try
{
laborCost = std::stod(laborCostString);
}
catch (...)
{
throw std::runtime_error("Invalid labor cost");
}
util::State status = util::getState(statusString);
return Factory::getObject<Service>(
id,
name,
inventoryItemIDs,
laborCost,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for service serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Name,InventoryIDs,LaborCost,Status")
*/
std::string Service::getHeaders()
{
return "ID,Name,InventoryIDs,LaborCost,Status";
}
@@ -1,6 +1,16 @@
/*
File: Service.h
Description: Declares the Service class which represents a vehicle service in the Vehicle Service Management System.
Each service includes a unique ID, name, required inventory items, labor cost, and status.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class InventoryItem;
@@ -11,14 +21,17 @@ private:
static int m_uid;
std::string m_id;
std::string m_name;
util::Vector<std::string> m_requiredInventoryItemIDs;
util::Map<std::string, InventoryItem*> m_requiredInventoryItems;
double m_laborCost;
util::State m_status;
public:
Service();
Service(const std::string& name, const util::Map<std::string, InventoryItem*>& requiredInventoryItems, double laborCost);
Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State state);
const std::string& getId() const;
const std::string& getName() const;
const util::Vector<std::string>& getRequiredInventoryItemIDs() const;
const util::Map<std::string, InventoryItem*>& getRequiredInventoryItems() const;
double getLaborCost() const;
util::State getState() const;
@@ -27,4 +40,7 @@ public:
void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems);
void setLaborCost(double laborCost);
void setState(util::State status);
std::string serialize() const;
static Service* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -6,36 +6,45 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include <sstream>
#include "ServiceBooking.h"
#include "Service.h"
#include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int ServiceBooking::m_uid = 0;
/*
Function: ServiceBooking
Description: Default constructor that initializes a new service booking
with a unique ID, no customer or technician, and zero discount.
Parameter: None
Return type: Constructor
Description: Default constructor that initializes a new service booking with a unique ID,
null customer, and zero discount percentage.
Parameters: None
Returns: A new ServiceBooking object.
*/
ServiceBooking::ServiceBooking()
: m_id("SRV" + std::to_string(++m_uid)),
: m_id("SBK" + std::to_string(++m_uid)),
m_customer(nullptr),
m_assignedTechnician(nullptr),
m_status(util::ServiceJobStatus::PENDING),
m_discountPercentage(0.0) {}
/*
Function: ServiceBooking
Description: Parameterized constructor that initializes a service booking
with customer, vehicle, services, and discount details.
Parameter: util::ServiceJobStatus status - current booking status
const util::Map<std::string, Service*>& services - map of services
const std::string& customerId - ID of the customer
User* customer - pointer to the customer object
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
double discountPercentage - discount applied to the booking
Return type: Constructor
Description: Parameterized constructor that initializes a new service booking with a unique ID and specified details.
Parameters:
- id: Booking ID string.
- status: Current status of the booking (e.g., PENDING, COMPLETED).
- services: Map of services included in the booking.
- customerId: ID of the customer.
- customer: Pointer to the User object representing the customer.
- vehicleNumber: Vehicle registration number.
- vehicleBrand: Brand of the vehicle.
- vehicleModel: Model of the vehicle.
- discountPercentage: Discount applied to the booking.
Returns:
- A new ServiceBooking object.
*/
ServiceBooking::ServiceBooking(
util::ServiceJobStatus status,
@@ -48,7 +57,7 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleModel,
double discountPercentage
)
: m_id("SRV" + std::to_string(++m_uid)),
: m_id("SBK" + std::to_string(++m_uid)),
m_status(status),
m_services(services),
m_customerId(customerId),
@@ -60,6 +69,60 @@ ServiceBooking::ServiceBooking(
m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage)
{
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
Function: ServiceBooking (parameterized constructor with ID)
Description: Initializes a service booking with an existing ID, status, service IDs,
customer details, vehicle details, technician ID, and discount percentage.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique booking ID
- status: util::ServiceJobStatus, job status of the booking
- serviceIDs: const util::Vector<std::string>&, IDs of booked services
- customerId: const std::string&, ID of the customer
- vehicleNumber: const std::string&, vehicle number
- vehicleBrand: const std::string&, vehicle brand
- vehicleModel: const std::string&, vehicle model
- assignedTechnicianId: const std::string&, ID of the assigned technician
- discountPercentage: double, discount applied
Returns:
- A new ServiceBooking object
*/
ServiceBooking::ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
)
: m_id(id),
m_status(status),
m_serviceIDs(serviceIDs),
m_customerId(customerId),
m_customer(nullptr),
m_vehicleNumber(vehicleNumber),
m_vehicleBrand(vehicleBrand),
m_vehicleModel(vehicleModel),
m_assignedTechnicianId(assignedTechnicianId),
m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
@@ -84,6 +147,25 @@ util::ServiceJobStatus ServiceBooking::getStatus() const
return m_status;
}
/*
Function: getServiceIDs
Description: Retrieves the IDs of services booked.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Service IDs
*/
const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
{
return m_serviceIDs;
}
/*
Function: getServices
Description: Retrieves the services associated with the booking.
Parameter: None
Return type: const util::Map<std::string, Service*>&
*/
/*
Function: getServices
Description: Retrieves the services associated with the booking.
@@ -213,6 +295,13 @@ Return type: void
void ServiceBooking::setServices(const util::Map<std::string, Service*>& services)
{
m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
@@ -301,4 +390,131 @@ Return type: void
void ServiceBooking::setDiscountPercentage(double discountPercentage)
{
m_discountPercentage = discountPercentage;
}
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
/*
Function: serialize
Description: Serializes the service booking into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized booking record
*/
std::string ServiceBooking::serialize() const
{
std::ostringstream serializedBooking;
serializedBooking << m_id << ','
<< util::getServiceJobStatusString(m_status) << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< m_customerId << ','
<< m_vehicleNumber << ','
<< m_vehicleBrand << ','
<< m_vehicleModel << ','
<< m_assignedTechnicianId << ','
<< m_discountPercentage << ',';
return serializedBooking.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ServiceBooking object.
Parameters:
- record: const std::string&, serialized booking record
Returns:
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
Throws:
- std::runtime_error if discount percentage parsing fails
*/
ServiceBooking* ServiceBooking::deserialize(const std::string& record)
{
std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
std::string serviceJobStatusString, serviceIDsString, discountPercentageString;
double discountPercentage;
std::istringstream serializedBooking(record);
getline(serializedBooking, id, ',');
getline(serializedBooking, serviceJobStatusString, ',');
getline(serializedBooking, serviceIDsString, ',');
getline(serializedBooking, customerId, ',');
getline(serializedBooking, vehicleNumber, ',');
getline(serializedBooking, vehicleBrand, ',');
getline(serializedBooking, vehicleModel, ',');
getline(serializedBooking, assignedTechnicianId, ',');
getline(serializedBooking, discountPercentageString, ',');
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid discount percentage");
}
util::ServiceJobStatus status = util::getServiceJobStatus(serviceJobStatusString);
return Factory::getObject<ServiceBooking>(
id,
status,
serviceIDs,
customerId,
vehicleNumber,
vehicleBrand,
vehicleModel,
assignedTechnicianId,
discountPercentage
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for service booking serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage")
*/
std::string ServiceBooking::getHeaders()
{
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
}
@@ -9,6 +9,7 @@ Date:19-May-2026
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class Service;
@@ -20,6 +21,7 @@ private:
static int m_uid;
std::string m_id;
util::ServiceJobStatus m_status;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services;
std::string m_customerId;
User* m_customer;
@@ -42,8 +44,20 @@ public:
const std::string& vehicleModel,
double discountPercentage
);
ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
);
const std::string& getId() const;
util::ServiceJobStatus getStatus() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const;
const std::string& getCustomerId() const;
User* getCustomer() const;
@@ -64,4 +78,7 @@ public:
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(User* assignedTechnician);
void setDiscountPercentage(double discountPercentage);
std::string serialize() const;
static ServiceBooking* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,14 +1,48 @@
/*
File: User.cpp
Description: Implements the User class which represents system users in the Vehicle Service Management System.
Provides constructors, destructor, accessors, and mutators for user details such as ID, username,
password, name, phone, email, role, state, and notifications.
Author: Trenser
Date: 19-May-2026
*/
#include <sstream>
#include "User.h"
#include "Notification.h"
#include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int User::m_uid = 0;
/*
Function: User
Description: Default constructor that initializes a new user with a unique ID,
default role as CUSTOMER, and active state.
Parameters:
- None
Returns:
- A new User object.
*/
User::User()
: m_id("USR" + std::to_string(++m_uid)),
m_type(util::UserType::CUSTOMER),
m_status(util::State::ACTIVE) {}
/*
Function: User
Description: Parameterized constructor that initializes a new user with a unique ID and specified details.
Parameters:
- userName: Username for login.
- password: Password for authentication.
- name: Full name of the user.
- phone: Phone number of the user.
- email: Email address of the user.
- role: Role of the user (CUSTOMER, ADMIN, TECHNICIAN, etc.).
Returns:
- A new User object.
*/
User::User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role)
: m_id("USR" + std::to_string(++m_uid)),
m_userName(userName),
@@ -19,104 +53,339 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role),
m_status(util::State::ACTIVE) {}
User::~User()
/*
Function: User (parameterized constructor with ID)
Description: Initializes a user with an existing ID, credentials, personal details,
role, and state. Updates UID tracking based on ID.
Parameters:
- userId: const std::string&, unique user ID
- userName: const std::string&, username
- password: const std::string&, password
- name: const std::string&, full name
- phone: const std::string&, phone number
- email: const std::string&, email address
- role: util::UserType, role of the user
- status: util::State, state of the user (ACTIVE/INACTIVE)
Returns:
- A new User object
*/
User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status)
: m_id(userId),
m_userName(userName),
m_password(password),
m_name(name),
m_phone(phone),
m_email(email),
m_type(role),
m_status(status)
{
for (int index = 0; index < m_notifications.getSize(); index++)
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
delete m_notifications.getValues()[index];
m_uid = idNumber;
}
}
/*
Function: ~User
Description: Destructor that cleans up dynamically allocated notifications associated with the user.
Parameters:
- None
Returns:
- void
*/
User::~User()
{
auto values = m_notifications.getValues();
for (int index = 0; index < values.getSize(); index++)
{
delete values[index];
}
}
/*
Function: getId
Description: Retrieves the unique ID of the user.
Returns:
- const std::string& representing the user ID.
*/
const std::string& User::getId() const
{
return m_id;
}
/*
Function: getUserName
Description: Retrieves the username of the user.
Returns:
- const std::string& representing the username.
*/
const std::string& User::getUserName() const
{
return m_userName;
}
/*
Function: getPassword
Description: Retrieves the password of the user.
Returns:
- const std::string& representing the password.
*/
const std::string& User::getPassword() const
{
return m_password;
}
/*
Function: getName
Description: Retrieves the full name of the user.
Returns:
- const std::string& representing the name.
*/
const std::string& User::getName() const
{
return m_name;
}
/*
Function: getPhone
Description: Retrieves the phone number of the user.
Returns:
- const std::string& representing the phone number.
*/
const std::string& User::getPhone() const
{
return m_phone;
}
/*
Function: getEmail
Description: Retrieves the email address of the user.
Returns:
- const std::string& representing the email.
*/
const std::string& User::getEmail() const
{
return m_email;
}
/*
Function: getNotifications
Description: Retrieves the map of notifications associated with the user.
Returns:
- util::Map<std::string, Notification*>& representing the notifications.
*/
util::Map<std::string, Notification*>& User::getNotifications()
{
return m_notifications;
}
/*
Function: getUserType
Description: Retrieves the role of the user.
Returns:
- util::UserType representing the user role.
*/
util::UserType User::getUserType() const
{
return m_type;
}
/*
Function: getState
Description: Retrieves the current state (ACTIVE/INACTIVE) of the user.
Returns:
- util::State representing the user state.
*/
util::State User::getState() const
{
return m_status;
}
/*
Function: setId
Description: Sets the unique ID of the user.
Parameters:
- id: New user ID string.
Returns:
- void
*/
void User::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setUserName
Description: Sets the username of the user.
Parameters:
- userName: New username string.
Returns:
- void
*/
void User::setUserName(const std::string& userName)
{
m_userName = userName;
}
/*
Function: setPassword
Description: Sets the password of the user.
Parameters:
- password: New password string.
Returns:
- void
*/
void User::setPassword(const std::string& password)
{
m_password = password;
}
/*
Function: setName
Description: Sets the full name of the user.
Parameters:
- name: New name string.
Returns:
- void
*/
void User::setName(const std::string& name)
{
m_name = name;
}
/*
Function: setPhone
Description: Sets the phone number of the user.
Parameters:
- phone: New phone number string.
Returns:
- void
*/
void User::setPhone(const std::string& phone)
{
m_phone = phone;
}
/*
Function: setEmail
Description: Sets the email address of the user.
Parameters:
- email: New email string.
Returns:
- void
*/
void User::setEmail(const std::string& email)
{
m_email = email;
}
/*
Function: addNotification
Description: Adds a new notification to the users notification map.
Parameters:
- notification: Pointer to the Notification object.
Returns:
- void
*/
void User::addNotification(Notification* notification)
{
m_notifications.insert(notification->getId(), notification);
if (notification)
{
m_notifications.insert(notification->getId(), notification);
}
}
/*
Function: setRole
Description: Sets the role of the user.
Parameters:
- role: New user role value.
Returns:
- void
*/
void User::setRole(util::UserType role)
{
m_type = role;
}
/*
Function: setState
Description: Sets the state (ACTIVE/INACTIVE) of the user.
Parameters:
- status: New state value.
Returns:
- void
*/
void User::setState(util::State status)
{
m_status = status;
}
void User::update(Notification* notification)
/*
Function: serialize
Description: Serializes the user into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized user record
*/
std::string User::serialize() const
{
std::ostringstream serializedUser;
serializedUser << m_id << ','
<< m_userName << ','
<< m_password << ','
<< m_name << ','
<< m_phone << ','
<< m_email << ','
<< util::getUserTypeString(m_type) << ','
<< util::getStateString(m_status);
return serializedUser.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a User object.
Parameters:
- record: const std::string&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
User* User::deserialize(const std::string& record)
{
std::string id, name, username, phone, password, email;
std::string userTypeString, stateString;
std::istringstream serializedUser(record);
getline(serializedUser, id, ',');
getline(serializedUser, username, ',');
getline(serializedUser, password, ',');
getline(serializedUser, name, ',');
getline(serializedUser, phone, ',');
getline(serializedUser, email, ',');
getline(serializedUser, userTypeString, ',');
getline(serializedUser, stateString);
util::UserType userType = util::getUserType(userTypeString);
util::State status = util::getState(stateString);
return Factory::getObject<User>(id,
username,
password,
name,
phone,
email,
userType,
status);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for user serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
*/
std::string User::getHeaders()
{
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
}
@@ -1,3 +1,12 @@
/*
File: User.h
Description: Declares the User class which represents system users in the Vehicle Service Management System.
Each user has a unique ID, credentials, personal details, notifications, role type, and status.
The User class also implements the Observer interface to handle notifications.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -22,6 +31,7 @@ private:
public:
User();
User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role);
User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status);
~User();
const std::string& getId() const;
const std::string& getUserName() const;
@@ -38,8 +48,10 @@ public:
void setName(const std::string& name);
void setPhone(const std::string& phone);
void setEmail(const std::string& email);
void addNotification(Notification* notification);
void addNotification(Notification* notification) override;
void setRole(util::UserType role);
void setState(util::State status);
void update(Notification* notification) override;
std::string serialize() const;
static User* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,11 +1,12 @@
/*
File: AuthenticationManagementService.cpp
Description: Implementation file containing the method definitions of the
AuthenticationManagementService class, including login, logout,
password change, and retrieval of the authenticated user.
AuthenticationManagementService class, including logout and
password change logic.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "AuthenticationManagementService.h"
#include "User.h"
@@ -6,6 +6,7 @@ Description: Header file declaring the AuthenticationManagementService class, wh
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "DataStore.h"
@@ -1 +1,341 @@
/*
File: InventoryManagementService.cpp
Description: Implements the InventoryManagementService class, which manages inventory
items and observer relationships within the system. Provides methods
for loading and saving inventory items from persistent storage, as well
as attaching and persisting observers for notification handling.
Author: Trenser
Date: 22-May-2026
*/
#include <stdexcept>
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h"
#include "InventoryManagementService.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
#include "Vector.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{};
/*
Function: sendLowStockAlertsToAdmins (static helper)
Description: Sends low stock alert notifications to all admin users for a given inventory item.
Parameters:
- inventoryManagementService: InventoryManagementService&, service used to send notifications
- inventoryItem: const InventoryItem*, pointer to the low-stock inventory item
- adminUsers: const util::Vector<User*>&, list of admin users to notify
Returns:
- None
*/
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{
int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++)
{
std::string title = "Low Stock Alert";
std::string message = "The inventory item with ID " + inventoryItem->getId() + " has very low quantity in the inventory";
inventoryManagementService.sendNotification(
adminUsers[index],
title,
message
);
}
}
/*
Function: sendLowStockAlerts
Description: Sends alerts to user for inventory items with low stock
Parameters:
- None
Returns:
- None
*/
void InventoryManagementService::sendLowStockAlerts()
{
auto& inventoryItems = m_dataStore.getInventoryItems();
if (inventoryItems.isEmpty())
{
return;
}
int inventoryItemsSize = inventoryItems.getSize();
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
util::Vector<User*> adminUsers;
for (int index = 0; index < usersMapSize; index++)
{
User* user = usersMap.getValueAt(index);
if (user->getUserType() == util::UserType::ADMIN)
{
adminUsers.push_back(user);
}
}
int adminUsersSize = adminUsers.getSize();
if (adminUsersSize < 1)
{
throw std::runtime_error("The system has no admins present!");
}
for (int index = 0; index < inventoryItemsSize; index++)
{
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
{
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
}
}
}
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
InventoryManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> InventoryManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
/*
Function: loadInventoryItems
Description: Loads inventory items from persistent storage into the datastore.
Uses FileManager to deserialize inventory items from the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
auto inventoryItemsMap = inventoryItemFileManager.load();
int numberOfInventoryItems = inventoryItemsMap.getSize();
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index);
}
}
/*
Function: saveInventoryItems
Description: Saves inventory items from the datastore to persistent storage.
Uses FileManager to serialize inventory items into the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
inventoryItemFileManager.save(inventoryItems);
}
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the InventoryManagementService.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadObservers()
{
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
}
/*
Function: saveObservers
Description: Saves the current observer IDs of the InventoryManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
/*
Function: addInventoryItem
Description: Creates a new inventory item using the Factory and inserts it
into the DataStore.
Parameter: const std::string& partName - name of the part
int quantity - initial quantity of the part
double price - price of the part
Return type: void
*/
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
m_dataStore.getInventoryItems().insert(newItem->getId(), newItem);
}
/*
Function: addInventoryItemStock
Description: Increases the stock quantity of an existing inventory item.
Parameter: const std::string& selectedItemId - ID of the inventory item
int quantity - quantity to add
Return type: void
*/
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
int index = m_dataStore.getInventoryItems().find(selectedItemId);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
int totalQuantity = item->getQuantity() + quantity;
item->setQuantity(totalQuantity);
}
}
}
/*
Function: getInventoryItems
Description: Retrieves all inventory items stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, InventoryItem*>
*/
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
{
return m_dataStore.getInventoryItems();
}
/*
Function: removeInventoryItem
Description: Marks an inventory item as inactive instead of deleting it.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
item->setState(util::State::INACTIVE);
}
}
}
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the DataStore.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: InventoryItem*
*/
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
return m_dataStore.getInventoryItems().getValueAt(index);
}
return nullptr;
}
/*
Function: attach
Description: Adds a user to the observer list for receiving inventory notifications.
Parameters:
- user: User*, pointer to the user to be attached as an observer
Returns:
- None
*/
void InventoryManagementService::attach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
}
/*
Function: detach
Description: Removes a user from the observer list so they no longer receive inventory notifications.
Parameters:
- user: User*, pointer to the user to be detached from the observer list
Returns:
- None
*/
void InventoryManagementService::detach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
}
/*
Function: sendNotification
Description: Sends a notification to a user if they are subscribed as an observer.
Parameters:
- user: User*, pointer to the user receiving the notification
- title: std::string, title of the notification
- message: std::string, body/content of the notification
Returns:
- None
Throws:
- std::runtime_error if notification creation fails
*/
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
if (user)
{
if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
}
}
@@ -1,6 +1,16 @@
/*
File: InventoryManagementService.h
Description: Header file declaring the InventoryManagementService class,
which manages inventory items, stock updates, and notifications
related to low stock alerts. Inherits from NotificationManagementService.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "NotificationManagementService.h"
#include "DataStore.h"
@@ -11,14 +21,20 @@ class InventoryManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, InventoryItem*> getInventoryItems();
InventoryItem* getInventoryItem(const std::string& inventoryItemID);
void addInventoryItem(const std::string& partName, int quantity, double price);
void removeInventoryItem(const std::string& inventoryItemID);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void sendLowStockAlerts();
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadInventoryItems();
void saveInventoryItems();
void loadObservers();
void saveObservers();
};
@@ -1,6 +1,15 @@
/*
File: NotificationManagementService.h
Description: Declares the NotificationManagementService abstract class which defines the contract for managing notifications in the Vehicle Service Management System.
Implements the Subject interface and provides pure virtual methods for sending notifications and managing user subscriptions (attach/detach).
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Subject.h"
#include "Notification.h"
#include "User.h"
class NotificationManagementService : public Subject
@@ -10,4 +19,5 @@ public:
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
virtual void attach(User* user) = 0;
virtual void detach(User* user) = 0;
virtual util::Vector<std::string> getObserverIDs() = 0;
};
@@ -1 +1,387 @@
/*
File: PaymentManagementService.cpp
Description: Implements the PaymentManagementService class which manages payment-related operations
in the Vehicle Service Management System. Provides functionality for attaching/detaching observers,
sending notifications, and issuing payment reminders based on invoice status and thresholds.
Author: Trenser
Date: 20-May-2026
*/
#include <stdexcept>
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h"
#include "Invoice.h"
#include "JobCard.h"
#include "PaymentManagementService.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
util::Map<std::string, User*> PaymentManagementService::m_observers{};
/*
Function: attach
Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications.
Parameters:
- user: Pointer to the User object to be attached.
Returns:
- void
*/
void PaymentManagementService::attach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
}
/*
Function: detach
Description: Detaches a user from the observer list of the PaymentManagementService.
Parameters:
- user: Pointer to the User object to be detached.
Returns:
- void
*/
void PaymentManagementService::detach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
}
/*
Function: sendNotification
Description: Sends a notification to a user if they are registered as an observer.
Parameters:
- user: Pointer to the User object to receive the notification.
- title: Title of the notification.
- message: Message content of the notification.
Returns:
- void
Throws:
- std::runtime_error if notification creation fails.
*/
void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
if (user)
{
if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
}
}
/*
Function: sendPaymentReminders
Description: Iterates through all invoices in the datastore and sends payment reminders to customers
whose invoices are pending beyond the configured threshold duration.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::sendPaymentReminders()
{
auto& invoicesMap = m_dataStore.getInvoices();
int invoicesMapSize = invoicesMap.getSize();
for (int index = 0; index < invoicesMapSize; index++)
{
const Invoice* invoice = invoicesMap.getValueAt(index);
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
{
util::Timestamp invoiceCreationTimestamp = invoice->getInvoiceDate();
util::Timestamp currentTimestamp;
if (util::Timestamp::getDurationInHours(invoiceCreationTimestamp, currentTimestamp) >= config::threshold::PAYMENT_REMINDER_THRESHOLD_HOURS)
{
const ServiceBooking* serviceBooking = invoice->getBooking();
if (serviceBooking)
{
User* customer = serviceBooking->getCustomer();
if (customer)
{
std::string title = "Payment Reminder";
std::string message = "Your payment for Invoice ID " + invoice->getId() + " is still pending. Please complete the payment.";
sendNotification(customer, title, message);
}
}
}
}
}
}
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
PaymentManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> PaymentManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
/*
Function: loadInvoices
Description: Loads invoices from persistent storage into the datastore.
Validates associated service bookings and inventory parts before
attaching them to each invoice. Throws exceptions if invalid IDs
are encountered.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a booking ID or part ID is invalid
*/
void PaymentManagementService::loadInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& inventoryItems = m_dataStore.getInventoryItems();
auto invoicesMap = invoiceFileManager.load();
for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++)
{
Invoice* invoice = invoicesMap.getValueAt(invoiceIndex);
int bookingIndex = serviceBookings.find(invoice->getBookingId());
if (bookingIndex == -1)
{
throw std::runtime_error("Invalid Booking ID");
}
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
invoice->setBooking(booking);
util::Map<std::string, InventoryItem*> invoiceParts;
auto& partIDs = invoice->getPartIDs();
for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++)
{
const std::string& partID = partIDs[partIndex];
int inventoryIndex = inventoryItems.find(partID);
if (inventoryIndex == -1)
{
throw std::runtime_error("Invalid Part ID");
}
invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex);
}
invoice->setParts(invoiceParts);
invoices[invoice->getId()] = invoice;
}
}
/*
Function: saveInvoices
Description: Saves invoices from the datastore to persistent storage.
Uses FileManager to serialize invoices into the configured file.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
invoiceFileManager.save(invoices);
}
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the PaymentManagementService.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
void PaymentManagementService::loadObservers()
{
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
}
/*
Function: saveObservers
Description: Saves the current observer IDs of the PaymentManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveObservers()
{
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
}
/*
Function: createInventoryItemsMap (static helper)
Description: Builds a map of inventory items required for a given service and adds them to the bookings inventory map.
Parameters:
- completeInventoryItemMapOfBooking: util::Map<std::string, InventoryItem*>&, map to store inventory items for the booking
- currentService: const Service*, pointer to the current service
Returns:
- void
*/
static void createInventoryItemsMap(util::Map<std::string, InventoryItem*>& completeInventoryItemMapOfBooking, const Service* currentService)
{
auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems();
for (int iterator = 0; iterator < currentRequiredInventoryItems.getSize(); iterator++)
{
auto& currentRequiredInventoryItem = currentRequiredInventoryItems.getValueAt(iterator);
completeInventoryItemMapOfBooking.insert(currentRequiredInventoryItem->getId(), currentRequiredInventoryItem);
}
}
/*
Function: generateInvoice
Description: Generates an invoice for a completed service booking.
Validates that all job cards are completed, calculates labor and parts cost, applies discount,
and stores the invoice in the datastore.
Parameters:
- booking: ServiceBooking*, pointer to the service booking
Returns:
- void
Throws:
- std::runtime_error if booking is null or job cards are incomplete
*/
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
{
if (!booking)
{
throw std::runtime_error("Invoice generation failed: booking is null.");
}
double totalLaborCost = 0, totalPartsCost = 0, totalServiceCost = 0;
double discountPercentage = booking->getDiscountPercentage();
std::string bookingID = booking->getId();
util::Map<std::string, Service*> servicesInTheBookedService = booking->getServices();
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
util::Map<std::string, JobCard*> currentJobCards = m_dataStore.getJobCards();
for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++)
{
JobCard* currentJobCard = currentJobCards.getValueAt(iterator);
util::ServiceJobStatus currentJobCardStatus = currentJobCard->getStatus();
if (currentJobCard->getBookingId() == bookingID && currentJobCardStatus != util::ServiceJobStatus::CANCELLED && currentJobCardStatus != util::ServiceJobStatus::COMPLETED)
{
throw std::runtime_error("Invoice generation failed: Not all job cards are completed for booking '" + bookingID + "'.");
}
}
for (int iterator = 0; iterator < servicesInTheBookedService.getSize(); iterator++)
{
Service* currentService = servicesInTheBookedService.getValueAt(iterator);
if (currentService)
{
createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService);
totalLaborCost += currentService->getLaborCost();
totalPartsCost += util::calculatePartsCost(currentService);
}
}
totalServiceCost = totalLaborCost + totalPartsCost;
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLaborCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
currentInvoices.insert(invoice->getId(), invoice);
}
/*
Function: getInvoices
Description: Retrieves all invoices associated with a specific customer.
Parameters:
- customerID: std::string, ID of the customer
Returns:
- util::Map<std::string, Invoice*> containing the customers invoices
*/
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
{
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
util::Map<std::string, Invoice*> currentUserInvoices;
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
{
Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
if (currentInvoice->getBooking()->getCustomerId() == customerID)
{
currentUserInvoices.insert(currentInvoice->getId(), currentInvoice);
}
}
return currentUserInvoices;
}
/*
Function: completePayment
Description: Completes payment for a specific invoice. Updates payment method, date, and status,
then sends a notification to the customer.
Parameters:
- invoiceID: std::string, ID of the invoice
- paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE)
Returns:
- void
Throws:
- std::runtime_error if the invoice ID is invalid
*/
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{
auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex != -1)
{
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
if (invoice && invoice->getStatus() != util::PaymentStatus::COMPLETED)
{
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentMethod(paymentMode);
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::COMPLETED);
std::string title, message;
title = "Payment successful";
message = "Payment successful for Invoice ID " + invoiceID;
sendNotification(currentUser, title, message);
}
}
else
{
throw std::runtime_error("Payment failed: invalid invoice ID.");
}
}
@@ -1,3 +1,12 @@
/*
File: PaymentManagementService.h
Description: Declares the PaymentManagementService class which manages payment operations in the Vehicle Service Management System.
Provides functionality to generate invoices, retrieve customer invoices, complete payments, send payment reminders,
and handle notifications using the Observer pattern.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -13,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
void generateInvoice(ServiceBooking* booking);
@@ -22,4 +32,8 @@ public:
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadInvoices();
void saveInvoices();
void loadObservers();
void saveObservers();
};
@@ -6,6 +6,7 @@ Description: Header file declaring the ServiceManagementService class, which man
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -22,6 +23,7 @@ class ServiceManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, Service*> getServices();
@@ -30,16 +32,27 @@ public:
void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel);
util::Map<std::string, ServiceBooking*> getServiceBookings();
util::Map<std::string, ServiceBooking*> getServiceBookings(const std::string& customerID);
ServiceBooking* getServiceBooking(const std::string& serviceID);
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID);
util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID);
void completeJob(const std::string& jobID);
void updateJobStatus(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID);
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadServices();
void saveServices();
void loadComboPackages();
void saveComboPackages();
void loadServiceBookings();
void saveServiceBookings();
void loadJobCards();
void saveJobCards();
void loadObservers();
void saveObservers();
};
@@ -6,15 +6,20 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "User.h"
#include "Enums.h"
#include "Config.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "PaymentManagementService.h"
#include "InventoryManagementService.h"
#include "Enums.h"
#include "Factory.h"
#include "FileManager.h"
#include "InventoryManagementService.h"
#include "Notification.h"
#include "PaymentManagementService.h"
#include "ServiceManagementService.h"
#include "User.h"
#include "UserManagementService.h"
#include "Vector.h"
#include "Validator.h"
/*
Function: ensureAdminExists
@@ -69,16 +74,18 @@ void UserManagementService::createUser(const std::string& username, const std::s
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return user->getUserName() == username;
}
);
if (index != -1)
if (util::isUsernameDuplicate(username, usersMap))
{
throw std::runtime_error("Username already exists");
}
if (util::isEmailDuplicate(email, usersMap))
{
throw std::runtime_error("Email already exists");
}
if (util::isPhoneDuplicate(phone, usersMap))
{
throw std::runtime_error("Phone already exists");
}
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser);
@@ -104,9 +111,228 @@ void UserManagementService::updateUserDetails(const std::string& userID, const s
int index = usersMap.find(userID);
if (index == -1)
{
throw std::runtime_error("User does not exist!");
throw std::runtime_error("User does not exist!\n");
}
User* user = usersMap.getValueAt(index);
if (email != user->getEmail())
{
if (util::isEmailDuplicate(email, usersMap))
{
throw std::runtime_error("Email already exists!\n");
}
}
if (phone != user->getPhone())
{
if (util::isPhoneDuplicate(phone, usersMap))
{
throw std::runtime_error("Phone number already exists!\n");
}
}
user->setEmail(email);
user->setPhone(phone);
}
/*
Function: getUserNotifications
Description: Retrieves all notifications associated with a given user ID.
Parameters:
- userID: The unique ID of the user whose notifications are to be retrieved.
Returns:
- util::Vector<Notification*> containing all notifications for the user.
Throws:
- std::runtime_error if no user is found with the given UserID or if the User object is invalid.
*/
util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID)
{
auto& usersMap = m_dataStore.getUsers();
if (usersMap.find(userID) == -1)
{
throw std::runtime_error("No user found with given UserID");
}
User* user = usersMap[userID];
if (user)
{
auto& notifications = user->getNotifications();
int numberOfNotifications = notifications.getSize();
util::Vector<Notification*> notificationsVector;
for (int index = 0; index < numberOfNotifications; index++)
{
notificationsVector.push_back(notifications.getValueAt(index));
}
return notificationsVector;
}
else
{
throw std::runtime_error("Invalid User object");
}
}
/*
Function: deleteNotification
Description: Deletes a specific notification associated with a given user ID.
Parameters:
- notificationID: The unique ID of the notification to be deleted.
- userID: The unique ID of the user whose notification is to be deleted.
Returns:
- void
Throws:
- std::runtime_error if no user is found with the given UserID or if no notification is found with the given NotificationID.
*/
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
{
auto& usersMap = m_dataStore.getUsers();
if (usersMap.find(userID) == -1)
{
throw std::runtime_error("No user found with given UserID");
}
User* user = usersMap[userID];
auto& notifications = user->getNotifications();
if (notifications.find(notificationID) == -1)
{
throw std::runtime_error("No notification found with given NotificationID");
}
notifications.remove(notificationID);
}
/*
Function: loadUsers
Description: Loads users and notifications from persistent storage into the datastore.
Validates that each notifications recipient exists and attaches the
notification to the corresponding user.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a notification recipient user ID is invalid
*/
void UserManagementService::loadUsers()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
auto usersMap = userFileManager.load();
auto notificationsMap = notificationFileManager.load();
int numberOfUsers = usersMap.getSize();
int numberOfNotifications = notificationsMap.getSize();
for (int index = 0; index < numberOfUsers; index++)
{
users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
}
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notificationsMap.getValueAt(index);
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = users.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = users.getValueAt(userIndex);
user->addNotification(notification);
}
}
/*
Function: saveUsers
Description: Saves users and their notifications from the datastore to persistent storage.
Collects notifications from all users into a single map before saving.
Parameters:
- None
Returns:
- void
*/
void UserManagementService::saveUsers()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
util::Map<std::string, Notification*> notifications;
for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
{
User* user = users.getValueAt(userIndex);
auto& userNotifications = user->getNotifications();
for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
{
notifications[userNotifications.getKeyAt(notificationIndex)] =
userNotifications.getValueAt(notificationIndex);
}
}
userFileManager.save(users);
notificationFileManager.save(notifications);
}
/*
Function: getUsers
Description: Retrieves all users stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, User*>
*/
util::Map<std::string, User*> UserManagementService::getUsers()
{
return m_dataStore.getUsers();
}
/*
Function: getUser
Description: Retrieves a specific user by ID from the DataStore.
Parameter: const std::string& userID - ID of the user
Return type: User*
*/
User* UserManagementService::getUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
return m_dataStore.getUsers().getValueAt(index);
}
return nullptr;
}
/*
Function: removeUser
Description: Marks a user as inactive in the DataStore instead of deleting them.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void UserManagementService::removeUser(const std::string& userID)
{
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
if (user->getUserType() == util::UserType::CUSTOMER)
{
serviceManagementService.cancelCustomerServiceBookings(userID);
}
if (user->getUserType() == util::UserType::TECHNICIAN)
{
serviceManagementService.cancelTechnicianJobs(userID);
}
user->setState(util::State::INACTIVE);
inventoryManagementService.detach(user);
paymentManagementService.detach(user);
serviceManagementService.detach(user);
}
}
}
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
@@ -25,9 +25,11 @@ public:
void updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone);
util::Map<std::string, User*> getUsers();
util::Map<std::string, User*> getUsers(util::UserType type);
User* getUser(const std::string& userID);
User* getUser (const std::string& userID);
void removeUser(const std::string& userID);
util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists();
void loadUsers();
void saveUsers();
};
@@ -4,8 +4,9 @@ Description: Header file declaring configuration constants for the Vehicle Servi
Includes default admin account details such as username, name, password,
email, and phone number.
Author: Trenser
Date:19-May-2026
Date: 21-May-2026
*/
#pragma once
namespace config
@@ -14,8 +15,29 @@ namespace config
{
constexpr const char* DEFAULT_ADMIN_USERNAME = "admin";
constexpr const char* DEFAULT_ADMIN_NAME = "admin";
constexpr const char* DEFAULT_ADMIN_PASSWORD = "";
constexpr const char* DEFAULT_ADMIN_PASSWORD = "admin";
constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss";
constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000";
}
namespace threshold
{
constexpr int INVENTORY_LOW_STOCK_THRESHOLD = 5;
constexpr int PAYMENT_REMINDER_THRESHOLD_HOURS = 168;
}
namespace file
{
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.csv";
constexpr const char* USER_FILE = "files/User.csv";
constexpr const char* NOTIFICATION_FILE = "files/Notification.csv";
constexpr const char* SERVICE_FILE = "files/Service.csv";
constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.csv";
constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.csv";
constexpr const char* JOBCARD_FILE = "files/JobCard.csv";
constexpr const char* INVOICE_FILE = "files/Invoice.csv";
constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.csv";
constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.csv";
constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.csv";
}
}
@@ -1,3 +1,12 @@
/*
File: Enums.h
Description: Declares enumerations and utility functions for user types, payment modes, payment status,
service job status, and state management in the Vehicle Service Management System.
Provides string conversion and parsing functions for each enum type.
Author: Trenser
Date: 19-May-2026
*/
#pragma once
#include <stdexcept>
@@ -13,7 +22,8 @@ namespace util
enum class PaymentMode
{
ONLINE,
OFFLINE
OFFLINE,
NOTSET
};
enum class PaymentStatus
@@ -24,8 +34,11 @@ namespace util
enum class ServiceJobStatus
{
PENDING,
STARTED,
COMPLETED
COMPLETED,
IN_PROGRESS,
CANCELLED
};
enum class State
@@ -34,6 +47,14 @@ namespace util
INACTIVE
};
/*
Function: getUserTypeString
Description: Converts a UserType enum value to its corresponding string representation.
Parameters:
- type: UserType enum value.
Returns:
- std::string representing the UserType.
*/
inline std::string getUserTypeString(UserType type)
{
switch (type)
@@ -48,6 +69,16 @@ namespace util
throw std::invalid_argument("Invalid UserType");
}
/*
Function: getUserType
Description: Converts a string value to its corresponding UserType enum.
Parameters:
- value: std::string representing the UserType.
Returns:
- UserType enum value.
Throws:
- std::invalid_argument if the string does not match a valid UserType.
*/
inline UserType getUserType(const std::string& value)
{
if (value == "ADMIN")
@@ -65,6 +96,14 @@ namespace util
throw std::invalid_argument("Invalid UserType string");
}
/*
Function: getPaymentModeString
Description: Converts a PaymentMode enum value to its corresponding string representation.
Parameters:
- mode: PaymentMode enum value.
Returns:
- std::string representing the PaymentMode.
*/
inline std::string getPaymentModeString(PaymentMode mode)
{
switch (mode)
@@ -73,10 +112,22 @@ namespace util
return "ONLINE";
case PaymentMode::OFFLINE:
return "OFFLINE";
case PaymentMode::NOTSET:
return "NOTSET";
}
throw std::invalid_argument("Invalid PaymentMode");
}
/*
Function: getPaymentMode
Description: Converts a string value to its corresponding PaymentMode enum.
Parameters:
- value: std::string representing the PaymentMode.
Returns:
- PaymentMode enum value.
Throws:
- std::invalid_argument if the string does not match a valid PaymentMode.
*/
inline PaymentMode getPaymentMode(const std::string& value)
{
if (value == "ONLINE")
@@ -87,9 +138,21 @@ namespace util
{
return PaymentMode::OFFLINE;
}
if (value == "NOTSET")
{
return PaymentMode::NOTSET;
}
throw std::invalid_argument("Invalid PaymentMode string");
}
/*
Function: getPaymentStatusString
Description: Converts a PaymentStatus enum value to its corresponding string representation.
Parameters:
- status: PaymentStatus enum value.
Returns:
- std::string representing the PaymentStatus.
*/
inline std::string getPaymentStatusString(PaymentStatus status)
{
switch (status)
@@ -102,6 +165,16 @@ namespace util
throw std::invalid_argument("Invalid PaymentStatus");
}
/*
Function: getPaymentStatus
Description: Converts a string value to its corresponding PaymentStatus enum.
Parameters:
- value: std::string representing the PaymentStatus.
Returns:
- PaymentStatus enum value.
Throws:
- std::invalid_argument if the string does not match a valid PaymentStatus.
*/
inline PaymentStatus getPaymentStatus(const std::string& value)
{
if (value == "PENDING")
@@ -117,18 +190,42 @@ namespace util
throw std::invalid_argument("Invalid PaymentStatus string");
}
/*
Function: getServiceJobStatusString
Description: Converts a ServiceJobStatus enum value to its corresponding string representation.
Parameters:
- status: ServiceJobStatus enum value.
Returns:
- std::string representing the ServiceJobStatus.
*/
inline std::string getServiceJobStatusString(ServiceJobStatus status)
{
switch (status)
{
case ServiceJobStatus::PENDING:
return "PENDING";
case ServiceJobStatus::STARTED:
return "STARTED";
case ServiceJobStatus::COMPLETED:
return "COMPLETED";
case ServiceJobStatus::CANCELLED:
return "CANCELLED";
case ServiceJobStatus::IN_PROGRESS:
return "IN_PROGRESS";
}
throw std::invalid_argument("Invalid ServiceJobStatus");
}
/*
Function: getServiceJobStatus
Description: Converts a string value to its corresponding ServiceJobStatus enum.
Parameters:
- value: std::string representing the ServiceJobStatus.
Returns:
- ServiceJobStatus enum value.
Throws:
- std::invalid_argument if the string does not match a valid ServiceJobStatus.
*/
inline ServiceJobStatus getServiceJobStatus(const std::string& value)
{
if (value == "STARTED")
@@ -139,31 +236,61 @@ namespace util
{
return ServiceJobStatus::COMPLETED;
}
if (value == "PENDING")
{
return ServiceJobStatus::PENDING;
}
if (value == "CANCELLED")
{
return ServiceJobStatus::CANCELLED;
}
if (value == "IN_PROGRESS")
{
return ServiceJobStatus::IN_PROGRESS;
}
throw std::invalid_argument("Invalid ServiceJobStatus string");
}
/*
Function: getStateString
Description: Converts a State enum value to its corresponding string representation.
Parameters:
- status: State enum value.
Returns:
- std::string representing the State.
*/
inline std::string getStateString(State status)
{
switch (status)
{
case State::ACTIVE:
return "STARTED";
return "ACTIVE";
case State::INACTIVE:
return "COMPLETED";
return "INACTIVE";
}
throw std::invalid_argument("Invalid State");
}
/*
Function: getState
Description: Converts a string value to its corresponding State enum.
Parameters:
- value: std::string representing the State.
Returns:
- State enum value.
Throws:
- std::invalid_argument if the string does not match a valid State.
*/
inline State getState(const std::string& value)
{
if (value == "ACTIVE")
{
return State::ACTIVE;
}
if (value == "COMPLETED")
if (value == "INACTIVE")
{
return State::INACTIVE;
}
throw std::invalid_argument("Invalid State string");
}
}
}
@@ -0,0 +1,109 @@
/*
File: FileHelper.h
Description: Provides utility functions for loading and saving records
from and to CSV-like text files. Ensures files are created
if missing and supports simple record persistence.
Author: Trenser
Date: 22-May-2026
*/
#pragma once
#include <fstream>
#include <string>
#include <stdexcept>
#include <direct.h>
#include "Vector.h"
namespace util
{
/*
Function: ensureDirectoryExists
Description: Creates all missing directories present in the given file path.
Iteratively parses the path and creates each directory level
using _mkdir() before file operations are performed.
Parameters:
- filePath: const std::string&, relative or absolute file path
Returns:
- void
Throws:
- None (_mkdir failures are intentionally ignored if directory already exists)
*/
inline void ensureDirectoryExists(const std::string& filePath)
{
size_t position = 0;
while ((position = filePath.find('/', position)) != std::string::npos)
{
std::string directory = filePath.substr(0, position);
if (!directory.empty())
{
(void)_mkdir(directory.c_str());
}
position++;
}
}
/*
Function: loadRecords
Description: Loads records from a given file path into a vector of strings.
Skips the header line if present. Creates the file if it does not exist.
Parameters:
- filePath: const std::string&, path to the file
Returns:
- util::Vector<std::string>: Vector containing all records (excluding header)
Throws:
- None (creates file if missing)
*/
inline util::Vector<std::string> loadRecords(const std::string& filePath)
{
util::Vector<std::string> records;
std::ifstream file(filePath);
if (!file.is_open())
{
ensureDirectoryExists(filePath);
std::ofstream newFile(filePath);
newFile.close();
file.open(filePath);
}
std::string line;
bool isHeader = true;
while (std::getline(file, line))
{
if (isHeader)
{
isHeader = false;
continue;
}
records.push_back(line);
}
return records;
}
/*
Function: saveRecords
Description: Saves records to a given file path. Overwrites existing content
and writes a header line followed by all records.
Parameters:
- filePath: const std::string&, path to the file
- records: const util::Vector<std::string>&, vector of records to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{
std::ofstream file(filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + filePath);
}
file << "Values" << '\n';
int numberOfRecords = records.getSize();
for (int index = 0; index < numberOfRecords; index++)
{
file << records[index] << '\n';
}
}
}
@@ -0,0 +1,119 @@
/*
File: FileManager.h
Description: Declares and implements a generic FileManager template class for
loading and saving objects to and from files. Uses serialization
and deserialization methods defined in the object type T.
Provides persistence support for system entities such as Users,
Services, InventoryItems, etc.
Author: Trenser
Date: 22-May-2026
*/
#pragma once
#include <stdexcept>
#include <string>
#include <fstream>
#include "Vector.h"
#include "Map.h"
#include "FileHelper.h"
namespace util
{
template <typename T> using objects = util::Map<std::string, T*>;
template <typename T>
class FileManager
{
private:
std::string m_filePath;
public:
FileManager() : m_filePath("") {}
FileManager(const std::string& filePath) : m_filePath(filePath) {}
objects<T> load();
void save(const objects<T>&);
};
/*
Function: load
Description: Loads records from the file into a map of objects.
Skips the header line, deserializes each record into an object of type T,
and stores them in a map keyed by object ID.
Parameters:
- None
Returns:
- util::Map<std::string, T*> containing deserialized objects
Throws:
- std::runtime_error if deserialization fails for any record
*/
template <typename T>
objects<T> FileManager<T>::load()
{
objects<T> records;
std::ifstream file(m_filePath);
if (!file.is_open())
{
ensureDirectoryExists(m_filePath);
std::ofstream newFile(m_filePath);
newFile.close();
file.open(m_filePath);
}
util::Vector<std::string> lines;
std::string line;
while (std::getline(file, line))
{
lines.push_back(line);
}
int numberOfLines = lines.getSize();
bool isHeader = true;
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
const auto& record = lines[lineIndex];
if (isHeader)
{
isHeader = false;
continue;
}
auto object = T::deserialize(record);
if (!object)
{
throw std::runtime_error("Failed to deserialize record");
}
records[object->getId()] = object;
}
return records;
}
/*
Function: save
Description: Saves records to the file. Serializes each object of type T into a string,
writes a header line, and then writes all serialized records to the file.
Parameters:
- records: const util::Map<std::string, T*>&, map of objects to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
template <typename T>
void FileManager<T>::save(const objects<T>& records)
{
util::Vector<std::string> lines;
lines.push_back(T::getHeaders());
int numberOfRecords = records.getSize();
for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++)
{
const auto& record = records.getValueAt(recordIndex);
lines.push_back(record->serialize());
}
std::ofstream file(m_filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + m_filePath);
}
int numberOfLines = lines.getSize();
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
file << lines[lineIndex] << '\n';
}
}
}
@@ -34,7 +34,7 @@ namespace util
/*
* Function: read
* Description: Reads a line of text input from console into a string.
* Description: Reads a line of text input from console into a string and cleans it up.
* Parameters:
* value - reference to a string where the input will be stored
* Returns:
@@ -43,6 +43,15 @@ namespace util
inline void read(std::string& value)
{
std::getline(std::cin >> std::ws, value);
std::string cleanedValue;
for (int index = 0; index < value.length(); index++)
{
if (value[index] != ',')
{
cleanedValue += value[index];
}
}
value = cleanedValue;
}
/*
@@ -53,6 +62,7 @@ namespace util
*/
inline void pressEnter()
{
std::cout << std::endl;
system("pause");
}
}
@@ -21,4 +21,28 @@ namespace util
{
std::cout << "\x1B[2J\x1B[H" << std::flush;
}
/*
Function: truncateString
Description:
Truncates a string if its length exceeds the given maximum length.
The truncated string ends with "..." to indicate omitted characters.
Parameters:
- text: const std::string&, input string to truncate
- maxLength: size_t, maximum allowed length of the returned string
Returns:
- std::string: Original string if within limit, otherwise truncated string with "..."
*/
inline std::string truncateString(const std::string& text, size_t maxLength)
{
if (text.length() <= maxLength)
{
return text;
}
if (maxLength <= 3)
{
return std::string(maxLength, '.');
}
return text.substr(0, maxLength - 3) + "...";
}
}
@@ -0,0 +1,36 @@
/*
File: StringHelper.h
Description: Provides utility functions for extracting numeric values from strings.
Useful for parsing IDs, codes, or mixed alphanumeric inputs where
digits need to be isolated and converted into integers.
Author: Trenser
Date: 22-May-2026
*/
#include <cctype>
#include <string>
namespace util
{
/*
Function: extractNumber
Description: Extracts all digits from the given string and converts them into an integer.
Ignores non-digit characters. For example, "abc123xyz" returns 123.
Parameters:
- input: const std::string&, the input string containing digits and/or other characters
Returns:
- int: The integer value formed by concatenating all digits in the string
*/
inline int extractNumber(const std::string& input)
{
int result = 0;
for (char character : input)
{
if (std::isdigit(static_cast<unsigned char>(character)))
{
result = result * 10 + (character - '0');
}
}
return result;
}
}
@@ -1,49 +1,102 @@
/*
File: Utility.h
Description: Header file declaring utility functions used across the system,
including cost calculation for services and combo packages.
Description: Header file declaring utility functions used across the system
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Service.h"
#include "ComboPackage.h"
#include "DataStore.h"
#include "FileHelper.h"
#include "InventoryItem.h"
#include "NotificationManagementService.h"
#include "Service.h"
/*
Function: calculatePartsCost
Description: Calculates the total cost of parts required for a given service
by summing the prices of all associated inventory items.
Parameter: const Service* service - pointer to the service object
Return type: double - total cost of required parts
*/
inline double calculatePartsCost(const Service* service)
namespace util
{
double cost = 0;
auto& requiredInventoryItems = service->getRequiredInventoryItems();
int requiredInventoryItemsSize = requiredInventoryItems.getSize();
for (int index = 0; index < requiredInventoryItemsSize; index++)
/*
Function: calculatePartsCost
Description: Calculates the total cost of parts required for a given service
by summing the prices of all associated inventory items.
Parameter: const Service* service - pointer to the service object
Return type: double - total cost of required parts
*/
inline double calculatePartsCost(const Service* service)
{
cost += requiredInventoryItems.getValueAt(index)->getPrice();
double cost = 0;
auto& requiredInventoryItems = service->getRequiredInventoryItems();
int requiredInventoryItemsSize = requiredInventoryItems.getSize();
for (int index = 0; index < requiredInventoryItemsSize; index++)
{
cost += requiredInventoryItems.getValueAt(index)->getPrice();
}
return cost;
}
return cost;
}
/*
Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing
the labor and parts costs of all services included in the package.
Parameter: const ComboPackage* comboPackage - pointer to the combo package object
Return type: double - estimated total cost of the combo package
*/
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{
double cost = 0;
auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
/*
Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing
the labor and parts costs of all services included in the package.
Parameter: const ComboPackage* comboPackage - pointer to the combo package object
Return type: double - estimated total cost of the combo package
*/
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{
const Service* service = services.getValueAt(index);
cost += calculatePartsCost(service) + service->getLaborCost();
double cost = 0;
auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
{
const Service* service = services.getValueAt(index);
cost += calculatePartsCost(service) + service->getLaborCost();
}
return cost;
}
return cost;
}
/*
Function: loadObservers
Description: Loads observer IDs from a file and attaches the corresponding users
to the notification management service. Validates that each observer ID
exists in the datastore before attaching.
Parameters:
- filePath: const std::string&, path to the file containing observer IDs
- service: NotificationManagementService*, pointer to the notification service
- dataStore: DataStore&, reference to the datastore containing users
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
{
auto observerIDs = util::loadRecords(filePath);
auto& users = dataStore.getUsers();
for (int index = 0; index < observerIDs.getSize(); index++)
{
const std::string& observerID = observerIDs[index];
int userIndex = users.find(observerID);
if (userIndex == -1)
{
throw std::runtime_error("Invalid Observer ID");
}
service->attach(users.getValueAt(userIndex));
}
}
/*
Function: saveObservers
Description: Saves the current observer IDs from the notification management service
to a file for persistence.
Parameters:
- filePath: const std::string&, path to the file where observer IDs will be saved
- service: NotificationManagementService*, pointer to the notification service
Returns:
- void
*/
inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
{
auto observerIDs = service->getObserverIDs();
util::saveRecords(filePath, observerIDs);
}
}
@@ -106,4 +106,70 @@ bool util::isPasswordValid(const std::string& password)
}
return hasUpper && hasLower && hasDigit && hasSpecial;
}
/*
* Function: isUsernameDuplicate
* Description: Checks if the given username already exists among active users.
* Parameters:
* username - string containing the username to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the username is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isUsernameDuplicate(const std::string& username, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getUserName() == username && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
}
/*
* Function: isPhoneDuplicate
* Description: Checks if the given phone number already exists among active users.
* Parameters:
* phone - string containing the phone number to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the phone number is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isPhoneDuplicate(const std::string& phone, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getPhone() == phone && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
}
/*
* Function: isEmailDuplicate
* Description: Checks if the given email address already exists among active users.
* Parameters:
* email - string containing the email address to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the email address is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isEmailDuplicate(const std::string& email, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getEmail() == email && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
}
@@ -9,10 +9,15 @@
#include<string>
#include<algorithm>
#include<cctype>
#include "Map.h"
#include "User.h"
namespace util
{
bool isPhoneNumberValid(const std::string&);
bool isEmailValid(const std::string&);
bool isPasswordValid(const std::string&);
bool isUsernameDuplicate(const std::string&, const util::Map<std::string, User*>&);
bool isPhoneDuplicate(const std::string&, const util::Map<std::string, User*>&);
bool isEmailDuplicate(const std::string&, const util::Map<std::string, User*>&);
}
@@ -1,89 +1,706 @@
#include "AdminMenu.h"
#include "InputHelper.h"
#include "OutputHelper.h"
/*
File: AdminMenu.cpp
Description: Implements the AdminMenu class which provides the administrators console interface
in the Vehicle Service Management System. Handles menu display, user input, and
admin-specific operations such as inventory management, technician management,
service creation, combo package management, job assignment, and notifications.
Author: Trenser
Date: 19-May-2026
*/
#include <iomanip>
#include <iostream>
#include "AdminMenu.h"
#include "Enums.h"
#include "InputHelper.h"
#include "InventoryItem.h"
#include "MenuHelper.h"
#include "OutputHelper.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "User.h"
#include "Utility.h"
#include "Validator.h"
/*
Function: showMenu
Description: Displays the admin menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void AdminMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
while (true)
{
try
{
int choice;
util::clear();
std::cout << "Admin Menu"
<< "\n1. View Stock Levels"
<< "\n2. Add Inventory Item"
<< "\n3. Remove Inventory Item"
<< "\n4. Check Stock Availability"
<< "\n5. Assign Job to Technician"
<< "\n6. Display Users"
<< "\n7. Add Technician"
<< "\n8. Remove Customer/Technician"
<< "\n9. Display Services"
<< "\n10. Create Service"
<< "\n11. Remove Service"
<< "\n12. Display Combo Packages"
<< "\n13. Create Combo Package"
<< "\n14. Remove Combo Package"
<< "\n15. View Notifications"
<< "\n16. Change Password"
<< "\n17. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
break;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
}
/*
Function: handleOperation
Description: Executes the corresponding admin operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool AdminMenu::handleOperation(int choice)
{
return false;
switch (choice)
{
case 1:
viewStockLevels();
break;
case 2:
addInventoryItem();
break;
case 3:
removeInventoryItem();
break;
case 4:
checkStockAvailability();
break;
case 5:
assignJob();
break;
case 6:
displayUsers();
break;
case 7:
addTechnician();
break;
case 8:
removeUser();
break;
case 9:
displayServices();
break;
case 10:
createService();
break;
case 11:
removeService();
break;
case 12:
displayComboPackages();
break;
case 13:
createComboPackages();
break;
case 14:
removeComboPackage();
break;
case 15:
viewNotifications();
break;
case 16:
changePassword();
break;
case 17:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
/*
Function: logout
Description: Logs out the currently authenticated admin user.
Parameter: None
Return type: void
*/
void AdminMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the admin to change their password after validation.
Parameter: None
Return type: void
*/
void AdminMenu::changePassword()
{
changePasswordHelper(m_controller);
}
/*
Function: viewStockLevels
Description: Displays all active inventory items with their details
including ID, part name, quantity, and price.
Parameter: None
Return type: void
*/
void AdminMenu::viewStockLevels()
{
util::clear();
auto inventoryItems = m_controller.getInventoryItems();
bool hasActiveItems = false;
std::cout << "View Stock Levels" << std::endl;
if (inventoryItems.isEmpty())
{
std::cout << "No items found in Inventory.\n";
util::pressEnter();
return;
}
for (int index = 0; index < inventoryItems.getSize(); index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item->getState() == util::State::ACTIVE)
{
hasActiveItems = true;
break;
}
}
if (!hasActiveItems)
{
std::cout << "No active Inventory Item found.\n";
util::pressEnter();
return;
}
std::cout << std::left << std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(15) << "Quantity"
<< std::setw(15) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
if (item->getState() != util::State::INACTIVE)
{
std::cout << std::left << std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(15) << item->getQuantity()
<< std::setw(15) << item->getPrice()
<< std::endl;
}
}
}
std::cout << "\n";
util::pressEnter();
}
/*
Function: addInventoryItem
Description: Allows the admin to either add a new inventory item
or increase the quantity of an existing item.
Parameter: None
Return type: void
*/
void AdminMenu::addInventoryItem()
{
util::clear();
int choice, quantity;
double price;
std::string partName;
std::cout << "Add Inventory Item\n";
std::cout << "1. Add new item \n2. Restock Item\n\nEnter your choice : ";
util::read(choice);
switch (choice)
{
case 1:
{
util::clear();
std::cout << "Enter Item Details\n";
std::cout << "Part Name : ";
util::read(partName);
std::cout << "Quantity : ";
util::read(quantity);
std::cout << "Price : ";
util::read(price);
m_controller.addInventoryItem(partName, quantity, price);
std::cout << "\nNew Item " << partName << " added to the Inventory.\n\n";
break;
}
case 2:
{
util::clear();
std::cout << "Select Item to Restock\n";
auto inventoryItems = m_controller.getInventoryItems();
addQuantityToItem(inventoryItems, m_controller);
break;
}
default:
{
std::cout << "\nEnter a valid choice.\n\n";
}
}
util::pressEnter();
}
/*
Function: removeInventoryItem
Description: Removes an active inventory item by marking it inactive
after user selection.
Parameter: None
Return type: void
*/
void AdminMenu::removeInventoryItem()
{
util::clear();
std::cout << "Remove Inventory Item\n";
auto inventoryItems = m_controller.getInventoryItems();
auto activeItems = filterActiveItems(inventoryItems);
int activeItemsSize = activeItems.getSize();
if (activeItemsSize == 0)
{
std::cout << "No items available in Inventory." << std::endl;
util::pressEnter();
return;
}
displayInventoryWithItems(activeItems);
int itemIndex;
std::cout << "Enter the index of the item to remove: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeItemsSize)
{
std::cout << "Invalid index selected." << std::endl;
util::pressEnter();
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
if(selectedItem->getState() != util::State::INACTIVE)
{
std::string selectedItemId = selectedItem->getId();
m_controller.removeInventoryItem(selectedItemId);
std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl;
}
}
util::pressEnter();
}
/*
Function: checkStockAvailability
Description: Checks if a specific inventory item is available
and displays its details if active.
Parameter: None
Return type: void
*/
void AdminMenu::checkStockAvailability()
{
util::clear();
std::string itemId;
std::cout << "Check Stock Availability \n";
std::cout << "Enter the Item ID : ";
util::read(itemId);
util::clear();
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
if (selectedItem != nullptr)
{
if (selectedItem->getState() != util::State::INACTIVE)
{
std::cout << "Item Details\n";
std::cout << "---------------------------------------------\n";
std::cout << "Item ID : " << selectedItem->getId() << "\n";
std::cout << "Part Name : " << selectedItem->getPartName() << "\n";
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
}
}
else
{
std::cout << "Item not Found" << std::endl;
}
util::pressEnter();
}
/*
Function: assignJob
Description: Allows the admin to assign pending service bookings to available technicians.
Creates job cards for selected services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::assignJob()
{
util::clear();
std::cout << "Assign Job to Technician\n";
std::string selectedService;
bool hasPendingService = false;
auto currentBookings = m_controller.getServiceBookings();
auto pendingServiceBookings = filterActiveServiceBookings(currentBookings);
auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN);
int bookingsSize = pendingServiceBookings.getSize();
util::Map<int, const ServiceBooking*> serviceBookingsMap;
util::Map<int, const User*> currentAvailableTechniciansMap;
if (listServiceBookings(pendingServiceBookings, bookingsSize, serviceBookingsMap))
{
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap);
if (selectedService)
{
if (availableTechnicians.getSize() != 0)
{
listAvailableTechnicians(availableTechnicians, availableTechnicians.getSize(), currentAvailableTechniciansMap);
const User* selectedTechnician = selectTechnician(currentAvailableTechniciansMap);
if (selectedTechnician)
{
auto& servicesInBooking = selectedService->getServices();
for (int iterator = 0; iterator < servicesInBooking.getSize(); iterator++)
{
m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId());
}
std::cout << "Job card created for each service and technician successfully assigned.\n\n";
}
}
else
{
std::cout << "No technicians are currently available.\n\n";
}
}
}
else
{
std::cout << "No pending service bookings available.\n\n";
}
util::pressEnter();
}
/*
Function: displayServices()
Description: Display all active services
Parameters:
- None
Returns:
- void
*/
void AdminMenu::displayServices()
{
util::clear();
std::cout << "List of all Services\n";
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
util::Map<std::string, const Service*> currentActiveServices = filterActiveServices(currentServices);
displayAllServices(currentActiveServices);
util::pressEnter();
}
/*
Function: createService
Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::createService()
{
util::clear();
std::cout << "Create Service\n";
std::string serviceName;
double labourCost;
std::cout << "Enter the service name: ";
util::read(serviceName);
util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems();
util::Map<std::string, const InventoryItem*> activeInventoryItems = filterActiveItems(currentInventoryItems);
util::Vector<std::string> selectedInventoryItems;
selectInventoryItems(activeInventoryItems,selectedInventoryItems);
if (selectedInventoryItems.isEmpty())
{
util::pressEnter();
return;
}
std::cout << "\nEnter the labour cost: ";
util::read(labourCost);
m_controller.createService(serviceName, selectedInventoryItems, labourCost);
std::cout << "\nService created sucessfully.\n\n";
util::pressEnter();
}
/*
Function: removeService
Description: Allows the admin to remove an existing service by selecting from available services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::removeService()
{
util::clear();
std::cout << "Remove Service\n";
std::string selectedServiceID;
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
util::Map<std::string, const Service*> currentActiveServices = filterActiveServices(currentServices);
selectedServiceID = selectServicesToRemove(currentActiveServices);
if (selectedServiceID != "")
{
m_controller.removeService(selectedServiceID);
std::cout << "Service removed successfully.\n\n";
}
else
{
std::cout << "Failed to remove service.\n\n";
}
util::pressEnter();
}
/*
Function: displayUsers
Description: Displays all users.
Parameter: None
Return type: void
*/
void AdminMenu::displayUsers()
{
util::clear();
auto listOfUsers = m_controller.getUsers();
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
int activeUserCount = listOfActiveUsers.getSize();
std::cout << "List of all Users\n";
if (activeUserCount < 1)
{
std::cout << "No Active users." << std::endl;
util::pressEnter();
return;
}
displayAllUsers(listOfActiveUsers);
util::pressEnter();
}
/*
Function: addTechnician
Description: Adds a new technician after validating username, password, email, and phone number.
Parameter: None
Return type: void
*/
void AdminMenu::addTechnician()
{
util::clear();
std::string username, name, password, email, phoneNumber;
std::cout << "Add Technician\n";
std::cout << "Enter Technician Username: ";
util::read(username);
std::cout << "Enter Technician Name: ";
util::read(name);
std::cout << "Enter Technician Password: ";
util::read(password);
if(!util::isPasswordValid(password))
{
std::cout << "\nError: Password is invalid!\n\n";
util::pressEnter();
return;
}
std::cout << "Enter Technician Email: ";
util::read(email);
if(!util::isEmailValid(email))
{
std::cout << "\nError: Email is invalid!\n\n";
util::pressEnter();
return;
}
std::cout << "Enter Technician Phone: ";
util::read(phoneNumber);
if(!util::isPhoneNumberValid(phoneNumber))
{
std::cout << "\nError: Phone Number is invalid!\n\n";
util::pressEnter();
return;
}
m_controller.createTechnician(username, name, password, email, phoneNumber);
std::cout << "\nTechnician Added Successfully.\n\n";
util::pressEnter();
}
/*
Function: removeUser
Description: Removes a selected active user (customer or technician) from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeUser()
{
util::clear();
int indexChoice;
auto listOfUsers = m_controller.getUsers();
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
int activeUserCount = listOfActiveUsers.getSize();
std::cout << "Remove User \n";
if (activeUserCount < 1)
{
std::cout << "No Active users." << std::endl;
util::pressEnter();
return;
}
displayAllUsers(listOfActiveUsers);
std::cout << "Enter the index of the user to delete : ";
util::read(indexChoice);
if (indexChoice < 1 || indexChoice > activeUserCount)
{
std::cout << "Error invalid index.\n" << std::endl;
util::pressEnter();
return;
}
const User* userToRemove = listOfActiveUsers.getValueAt(indexChoice - 1);
if (userToRemove != nullptr)
{
std::string userIdToRemove = userToRemove->getId();
m_controller.removeUser(userIdToRemove);
std::cout << userToRemove->getUserName() << " removed Successfully.\n";
}
util::pressEnter();
}
/*
Function: displayComboPackages()
Description: Display all active combo packages
Parameters:
- None
Returns:
- void
*/
void AdminMenu::displayComboPackages()
{
util::clear();
std::cout << "List of all Combo Packages\n";
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
util::Map<std::string, const ComboPackage*> currentActiveComboPackages = filterComboPackages(currentComboPackages);
displayAllComboPackages(currentActiveComboPackages);
util::pressEnter();
}
/*
Function: createComboPackages
Description: Creates a new combo package by selecting two active services and applying a discount.
Parameter: None
Return type: void
*/
void AdminMenu::createComboPackages()
{
util::clear();
std::cout << "Create Combo Packages\n";
auto serviceList = m_controller.getServices();
auto activeServices = filterActiveServices(serviceList);
int currentActiveServicesCount = activeServices.getSize();
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
util::Vector<std::string> selectedServiceID;
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++)
{
const Service* chosenService = nullptr;
while (true)
{
chosenService = selectServiceFromServices(activeServices);
if (!chosenService)
{
std::cout << "Failed to create combo package!\n\n";
util::pressEnter();
return;
}
bool alreadyChosen = false;
for (int iteratorOne = 0; iteratorOne < selectedServiceID.getSize(); iteratorOne++)
{
if (selectedServiceID[iteratorOne] == chosenService->getId())
{
alreadyChosen = true;
break;
}
}
if (alreadyChosen)
{
if (currentActiveServicesCount < 2)
{
break;
}
std::cout << "Service already selected. Please choose a different one." << std::endl;
continue;
}
selectedServiceID.push_back(chosenService->getId());
break;
}
if (currentActiveServicesCount < 2)
{
std::cout << "All the available services selected\n\n";
break;
}
}
std::string packageName;
double discountPercentage;
std::cout << "Enter combo package name: ";
util::read(packageName);
std::cout << "Enter discount percentage: ";
util::read(discountPercentage);
if (discountPercentage < 0.0 || discountPercentage > 100.0)
{
std::cout << "Error: Discount percentage must be between 0 and 100." << std::endl;
util::pressEnter();
return;
}
m_controller.createComboPackage(packageName, selectedServiceID, discountPercentage);
std::cout << "Combo package '" << packageName << "' created successfully." << std::endl;
util::pressEnter();
}
/*
Function: removeComboPackage
Description: Removes a selected combo package from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeComboPackage()
{
util::clear();
std::cout << "Remove Combo Package\n";
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
if (!selectedComboPackageID.empty())
{
m_controller.removeComboPackage(selectedComboPackageID);
std::cout << "Combo Package removed successfully.\n\n";
}
else
{
std::cout << "Combo package removal failed.\n\n";
}
util::pressEnter();
}
/*
Function: viewNotifications
Description: Displays notifications for the admin and allows deletion of notifications.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::viewNotifications()
{
viewAndDeleteNotification(m_controller);
}
@@ -1,3 +1,12 @@
/*
File: AdminMenu.h
Description: Header file declaring the AdminMenu class, which provides
administrative operations such as inventory management,
user management, service configuration, and notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -15,10 +24,13 @@ public:
void removeInventoryItem();
void checkStockAvailability();
void assignJob();
void displayServices();
void createService();
void removeService();
void displayUsers();
void addTechnician();
void removeUser();
void displayComboPackages();
void createComboPackages();
void removeComboPackage();
void viewNotifications();
@@ -6,18 +6,23 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include <iomanip>
#include "CustomerMenu.h"
#include "Service.h"
#include "InventoryItem.h"
#include "ComboPackage.h"
#include "Service.h"
#include "CustomerMenu.h"
#include "MenuHelper.h"
#include "Enums.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "InventoryItem.h"
#include "Invoice.h"
#include "Map.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "Timestamp.h"
#include "User.h"
#include "Validator.h"
#include "Vector.h"
#include "Utility.h"
#include "Map.h"
/*
Function: showMenu
@@ -25,6 +30,7 @@ Description: Displays the customer menu and handles user input until logout is s
Parameter: None
Return type: void
*/
void CustomerMenu::showMenu()
{
while (true)
@@ -125,19 +131,7 @@ Return type: void
*/
void CustomerMenu::changePassword()
{
std::string newPassword;
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
m_controller.changePassword(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!";
util::pressEnter();
return;
}
std::cout << "Password changed successfully";
util::pressEnter();
changePasswordHelper(m_controller);
}
/*
@@ -150,11 +144,12 @@ void CustomerMenu::updateDetails()
{
std::string email, phone;
util::clear();
std::cout << "Update Details\n";
std::cout << "Enter new email: ";
util::read(email);
if (!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
std::cout << "Error: Email is invalid!\n";
util::pressEnter();
return;
}
@@ -162,64 +157,15 @@ void CustomerMenu::updateDetails()
util::read(phone);
if (!util::isPhoneNumberValid(phone))
{
std::cout << "Error: Phone number is invalid!";
std::cout << "Error: Phone number is invalid!\n";
util::pressEnter();
return;
}
m_controller.updateUserDetails(email, phone);
std::cout << "Profile details updated successfully";
std::cout << "Profile details updated successfully\n";
util::pressEnter();
}
/*
Function: selectServiceFromServices
Description: Displays active services and allows the customer to select one by index.
Parameter: const util::Map<std::string, const Service*>& services - list of services
Return type: const Service* - selected service
*/
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
{
util::Map<int, const Service*> activeServicesMap;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
/*
Function: selectService
Description: Allows the customer to select a service, provide vehicle details,
@@ -230,9 +176,16 @@ Return type: void
void CustomerMenu::selectService()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto services = m_controller.getServices();
util::Vector<std::string> selectedServices;
util::clear();
std::cout << "Select a Service\n";
auto services = m_controller.getServices();
if (services.isEmpty())
{
std::cout << "No services available!";
util::pressEnter();
return;
}
util::Vector<std::string> selectedServices;
const Service* selectedService = selectServiceFromServices(services);
if (selectedService == nullptr)
{
@@ -242,6 +195,7 @@ void CustomerMenu::selectService()
}
selectedServices.push_back(selectedService->getId());
util::clear();
std::cout << "Enter Vehicle Details\n";
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
@@ -253,54 +207,6 @@ void CustomerMenu::selectService()
util::pressEnter();
}
/*
Function: selectComboPackageFromPackages
Description: Displays active combo packages and allows the customer to select one by index.
Parameter: const util::Map<std::string, const ComboPackage*>& comboPackages - list of combo packages
Return type: const ComboPackage* - selected combo package
*/
static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages)
{
util::Map<int, const ComboPackage*> activeComboPackages;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Combo Package ID"
<< std::setw(15) << "Combo Package Name"
<< std::setw(15) << "Estimate Cost"
<< std::endl;
for (int index = 0; index < comboPackages.getSize(); index++)
{
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
if (currentComboPackage->getState() != util::State::ACTIVE)
{
continue;
}
activeComboPackages.insert(currentIndex, currentComboPackage);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentComboPackage->getId()
<< std::setw(25) << currentComboPackage->getPackageName()
<< std::setw(15) << calculateComboServiceEstimatedCost(currentComboPackage)
<< std::endl;
currentIndex++;
}
if (activeComboPackages.getSize() == 0)
{
std::cout << "No active combo packages available." << std::endl;
return nullptr;
}
std::cout << "Enter combo package index: ";
util::read(userInputIndex);
if (activeComboPackages.find(userInputIndex) == -1)
{
std::cout << "Invalid combo package index." << std::endl;
return nullptr;
}
return activeComboPackages[userInputIndex];
}
/*
Function: selectComboPackage
Description: Allows the customer to select a combo package, provide vehicle details,
@@ -311,16 +217,27 @@ Return type: void
void CustomerMenu::selectComboPackage()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto comboPackages = m_controller.getComboPackages();
util::clear();
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
if (selectedComboPackage == nullptr)
std::cout << "Select a Combo Package\n";
auto comboPackages = m_controller.getComboPackages();
util::Map<std::string, const ComboPackage*> activeComboPackages = filterComboPackages(comboPackages);
if (activeComboPackages.isEmpty())
{
std::cout << "Failed to book combo package!";
std::cout << "No combo packages available!\n\n";
util::pressEnter();
return;
}
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(activeComboPackages);
if (selectedComboPackage == nullptr)
{
std::cout << "Failed to book combo package!\n\n";
util::pressEnter();
return;
}
std::cout << "Combo Package selected\n";
util::pressEnter();
util::clear();
std::cout << "Enter the vehicle details\n";
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
@@ -328,26 +245,157 @@ void CustomerMenu::selectComboPackage()
std::cout << "Enter vehicle model: ";
util::read(vehicleModel);
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Combo Package has been booked successfully";
std::cout << "Combo Package has been booked successfully\n\n";
util::pressEnter();
}
/*
Function: viewServiceHistory
Description: Displays the customers past service bookings in tabular format,
including booking ID, technician, vehicle details, discount percentage, and status.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewServiceHistory()
{
util::clear();
bool hasServiceHistory = false;
const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
std::cout << "View Service History" << std::endl;
if (serviceBookingsByCurrentUser.getSize() != 0)
{
std::cout << std::left
<< std::setw(15) << "Booking ID"
<< std::setw(20) << "Technician"
<< std::setw(20) << "Vehicle Brand"
<< std::setw(20) << "Vehicle Number"
<< std::setw(20) << "Vehicle Model"
<< std::setw(20) << "Discount %"
<< std::setw(20) << "Status"
<< std::endl;
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
{
const ServiceBooking* currentBooking = serviceBookingsByCurrentUser.getValueAt(iterator);
std::string technicianName = currentBooking->getAssignedTechnician() == nullptr
? "Not Assigned"
: currentBooking->getAssignedTechnician()->getName();
std::cout << std::left
<< std::setw(15) << currentBooking->getId()
<< std::setw(20) << technicianName
<< std::setw(20) << currentBooking->getVehicleBrand()
<< std::setw(20) << currentBooking->getVehicleNumber()
<< std::setw(20) << currentBooking->getVehicleModel()
<< std::setw(20) << currentBooking->getDiscountPercentage()
<< std::setw(20) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::endl;
hasServiceHistory = true;
}
}
if (!hasServiceHistory)
{
std::cout << "No history available." << std::endl;
}
util::pressEnter();
}
/*
Function: completePayments
Description: Allows the customer to complete pending payments for invoices.
Validates invoice selection and payment mode before completing payment.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::completePayments()
{
util::clear();
std::cout << "Complete Payments\n";
util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
if (currentInvoices.isEmpty())
{
std::cout << "No pending invoices available for payment.\n";
util::pressEnter();
return;
}
bool hasPending = false;
for (int index = 0; index < currentInvoices.getSize(); ++index)
{
const Invoice* invoice = currentInvoices.getValueAt(index);
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
{
hasPending = true;
break;
}
}
if (!hasPending)
{
std::cout << "No pending invoices available for payment.\n";
util::pressEnter();
return;
}
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
if (selectedID == "")
{
std::cout << "Payment failed.\n";
util::pressEnter();
return;
}
util::PaymentMode paymentMode = selectPaymentMode();
m_controller.completePayment(selectedID, paymentMode);
std::cout << "Payment completed successfully.\n";
util::pressEnter();
}
/*
Function: viewInvoices
Description: Displays invoices associated with the customer by calling displayInvoices.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewInvoices()
{
util::clear();
std::cout << "View Invoices\n";
util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser();
displayInvoices(currentUserInvoices);
util::pressEnter();
}
/*
Function: viewNotifications
Description: Displays notifications for the customer and allows deletion of notifications.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewNotifications()
{
viewAndDeleteNotification(m_controller);
}
/*
Function: configureNotifications
Description: Allows the customer to configure notification preferences for payment and service management.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::configureNotifications()
{
bool paymentServiceNotifications = getNotificationPreference("Payment Management Service");
bool serviceManagementNotifications = getNotificationPreference("Service Management Service");
m_controller.configureNotifications(paymentServiceNotifications, serviceManagementNotifications);
util::clear();
std::cout << "Notification preferences updated successfully.\n";
util::pressEnter();
}
@@ -7,6 +7,7 @@ Description: Header file declaring the CustomerMenu class, which provides
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
File diff suppressed because it is too large Load Diff
@@ -1,40 +1,184 @@
#include "TechnicianMenu.h"
#include "InputHelper.h"
#include "OutputHelper.h"
/*
File: TechnicianMenu.cpp
Description: Implementation file containing the method definitions of the
TechnicianMenu class, including menu handling, job completion,
notification viewing, password management, and logout logic.
Author: Trenser
Date:19-May-2026
*/
#include "Enums.h"
#include "InputHelper.h"
#include "JobCard.h"
#include "MenuHelper.h"
#include "OutputHelper.h"
#include "Service.h"
#include "TechnicianMenu.h"
#include "Validator.h"
/*
Function: showMenu
Description: Displays the technician menu in a loop until the user chooses to logout.
Handles exceptions and ensures smooth user interaction.
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
while (true)
{
try
{
int choice;
util::clear();
std::cout << "Technician Menu"
<< "\n1. Display My Jobs"
<< "\n2. Update Job Status"
<< "\n3. View Notifications"
<< "\n4. Change Password"
<< "\n5. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
break;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
}
/*
Function: handleOperation
Description: Executes the corresponding technician operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool TechnicianMenu::handleOperation(int choice)
{
return false;
switch (choice)
{
case 1:
displayJobs();
break;
case 2:
updateJobStatus();
break;
case 3:
viewNotifications();
break;
case 4:
changePassword();
break;
case 5:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
void TechnicianMenu::completeJob()
/*
Function: displayJobs
Description: Displays all Jobs assigned to a Technician
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::displayJobs()
{
util::clear();
std::cout << "My Jobs\n";
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<std::string, const JobCard*> jobCards = filterStartedJobCards(assignedJobCards);
displayAllJobs(jobCards);
util::pressEnter();
}
/*
Function: updateJobStatus
Description: Allows the technician to update a selected job card.
Validates selection and updates job status through the controller.
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::updateJobStatus()
{
util::clear();
std::cout << "Update Job Status\n";
int choice;
std::string selectedJobID;
util::ServiceJobStatus selectedJobStatus = util::ServiceJobStatus::PENDING;
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
std::cout << "Select the type of job you want to update\n1.Started\n2.Inprogress\nChoice: ";
util::read(choice);
if (choice == 1)
{
selectedJobStatus = util::ServiceJobStatus::STARTED;
}
else if (choice == 2)
{
selectedJobStatus = util::ServiceJobStatus::IN_PROGRESS;
}
else
{
std::cout << "Invalid choice. Please try again.\n";
util::pressEnter();
return;
}
util::Map<std::string, const JobCard*> selectedTypeJobCard = filterJobCards(assignedJobCards, selectedJobStatus);
selectedJobID = selectJobCardToUpdate(selectedTypeJobCard, selectedJobStatus);
if (!selectedJobID.empty())
{
m_controller.updateJobStatus(selectedJobID);
std::cout << "\nJob status updated.\n\n";
}
util::pressEnter();
}
/*
Function: viewNotifications
Description: Displays notifications for the technician and allows deletion of notifications.
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::viewNotifications()
{
viewAndDeleteNotification(m_controller);
}
/*
Function: logout
Description: Logs out the currently authenticated technician user.
Parameter: None
Return type: void
*/
void TechnicianMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the technician to change their password after validation.
Parameter: None
Return type: void
*/
void TechnicianMenu::changePassword()
{
changePasswordHelper(m_controller);
}
@@ -1,3 +1,12 @@
/*
File: TechnicianMenu.h
Description: Header file declaring the TechnicianMenu class, which provides
technician operations such as job completion, notification viewing,
password management, and logout functionality.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -8,6 +17,9 @@ private:
bool handleOperation(int choice);
public:
void showMenu();
void completeJob();
void displayJobs();
void updateJobStatus();
void viewNotifications();
void logout();
void changePassword();
};
@@ -6,11 +6,14 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include "UserInterface.h"
#include <iostream>
#include <stdexcept>
#include "Enums.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Enums.h"
#include "User.h"
#include "UserInterface.h"
#include "Validator.h"
/*
@@ -22,25 +25,43 @@ Return type: void
*/
void UserInterface::run()
{
bool isMenuActive = true;
while (isMenuActive)
try
{
try
m_controller.loadSystemData();
m_controller.runSystemChecks();
bool isMenuActive = true;
while (isMenuActive)
{
int choice;
util::clear();
std::cout << "Vehicle Service System\n1. Login\n2. Register Customer\n3. Exit\nEnter your Choice: ";
util::read(choice);
if (!handleOperation(choice))
try
{
isMenuActive = false;
int choice;
util::clear();
std::cout << "Vehicle Service System\n1. Login\n2. Register Customer\n3. Exit\nEnter your Choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
m_controller.saveSystemData();
}
catch (const std::invalid_argument& exception)
{
std::cout << "Exception: Invalid Argument: " << exception.what() << std::endl;
}
catch (const std::exception& exception)
{
std::cout << "Exception: " << exception.what() << std::endl;
}
catch (...)
{
std::cout << "Unknown error occurred." << std::endl;
}
}
@@ -81,6 +102,7 @@ void UserInterface::login()
{
std::string username, password;
util::clear();
std::cout << "Login\n";
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter password: ";
@@ -88,7 +110,7 @@ void UserInterface::login()
if (m_controller.login(username, password))
{
const User* authenticatedUser = m_controller.getAuthenticatedUser();
if (authenticatedUser != nullptr)
if (authenticatedUser && authenticatedUser->getState() != util::State::INACTIVE)
{
switch (authenticatedUser->getUserType())
{
@@ -106,10 +128,16 @@ void UserInterface::login()
break;
}
}
else if (authenticatedUser && authenticatedUser->getState() == util::State::INACTIVE)
{
std::cout << "\nError: Your account has been disabled. Please contact your Administrator.";
util::pressEnter();
}
}
else
{
std::cout << "\nError: Invalid Username or Password";
util::pressEnter();
}
}
@@ -125,6 +153,7 @@ void UserInterface::registerCustomer()
{
std::string username, name, email, phone, password;
util::clear();
std::cout << "Register Customer\n";
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter name: ";
@@ -7,6 +7,7 @@ Description: Header file declaring the UserInterface class, which provides
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
#include "AdminMenu.h"
@@ -26,4 +27,4 @@ public:
void run();
void login();
void registerCustomer();
};
};