Compare commits

..

74 Commits

Author SHA1 Message Date
Avinash Rajesh c64f3cff72 Implemented Review Fixes 2026-06-01 18:13:11 +05:30
Avinash Rajesh 20475ace73 Fix Duplicate Customer Notification Sent When Assigned Technician Is Removed
- Refactored processBookingCancellation to simplify parameters and remove redundant notification arguments.
- Added util::UserType parameter to differentiate cancellation flows for CUSTOMER vs TECHNICIAN.
- Updated cancelCustomerServiceBookings to use processBookingCancellation with util::UserType::CUSTOMER.
- Updated cancelTechnicianJobs to use processBookingCancellation with util::UserType::TECHNICIAN.
- Enhanced booking status handling by including IN_PROGRESS status in cancellation checks.
- Ensured job cards are consistently marked CANCELLED and inventory restored.
- Fixed duplicate notification issue where customers received multiple alerts when technician was removed.

Fixes #1807
2026-06-01 17:46:55 +05:30
joelthomastrenser 17f24b7733 Merged PR 1155: Implement Confirm Payment Functionality
- Added Controller::getAllInvoices – retrieves all invoices from PaymentManagementService and returns them as a read-only map
- Implemented Controller::confirmPayment – delegates payment confirmation for a given invoice ID to PaymentManagementService
- Introduced PaymentManagementService::getAllInvoice – provides access to all invoices stored in the datastore
- Added PaymentManagementService::confirmPayment – confirms payment for a specific invoice, updates payment date and status, and sends notification
- Extended util::PaymentStatus enum – added PAID status and updated string conversion
- Integrated AdminMenu::confirmPayment – validates invoice list, filters by status, allows selection, and confirms payment
- Updated CustomerMenu::completePayments – uses parameterized status filtering for invoice selection
- Enhanced MenuHelper::selectInvoiceFromUserForPayment – accepts requiredStatus parameter for flexible filtering
- Adjusted AdminMenu options – added "Confirm Payment" before Logout

Related work items: #1797
2026-06-01 17:34:41 +05:30
Avinash Rajesh 1032fc64bd Commit aee6356e: Implement Confirm Payment Functionality
<User Story> Complete Payments - 1797</User Story>

<Changes>
1. Added Controller::getAllInvoices
   - Retrieves all invoices from PaymentManagementService and returns them as a read-only map.
2. Implemented Controller::confirmPayment
   - Delegates payment confirmation for a given invoice ID to PaymentManagementService.
3. Introduced PaymentManagementService::getAllInvoice
   - Provides access to all invoices stored in the datastore.
4. Added PaymentManagementService::confirmPayment
   - Confirms payment for a specific invoice, updates payment date and status, and sends notification.
5. Extended util::PaymentStatus enum
   - Added PAID status and updated string conversion.
6. Integrated AdminMenu::confirmPayment
   - Validates invoice list, filters by status, allows selection, and confirms payment.
7. Updated CustomerMenu::completePayments
   - Uses parameterized status filtering for invoice selection.
8. Enhanced MenuHelper::selectInvoiceFromUserForPayment
   - Accepts requiredStatus parameter for flexible filtering.
9. Adjusted AdminMenu options
   - Added "Confirm Payment" before Logout.
</Changes>

<Test>
Acceptance Criteria:
1. Admin selects "Confirm Payment" from menu.
   - Verify system prompts and displays invoices filtered by status.
2. Admin selects invoice with status = PAID.
   - Verify payment confirmation updates date, sets status, and sends notification.
3. Admin attempts confirmation with empty invoice list.
   - Verify error message: "No pending invoices available for confirmation."
4. Customer completes payment.
   - Verify selection uses util::PaymentStatus::PENDING and payment flow works correctly.
5. Invalid invoice ID entered.
   - Verify system throws runtime_error with "Payment failed: invalid invoice ID."

Precondition:
1. Admin logged into system.
2. At least one invoice exists in datastore.
3. Notification system available.

Steps:
1. Navigate to Admin menu → Confirm Payment.
2. Select invoice with PAID status.
3. Confirm payment and check notification.
4. Attempt with empty invoice list.
5. Attempt with invalid invoice ID.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-06-01 17:30:27 +05:30
joelthomastrenser cfd1a2b675 Merged PR 1154: Implement Update Job Status for technician
- Renamed Controller and ServiceManagementService methods from completeJob to updateJobStatus for clarity and flexibility.
- Enhanced ServiceManagementService::updateJobStatus to support transitions:
- STARTED → INPROGRESS
- INPROGRESS → COMPLETED (with invoice generation and customer notification).
- Added INPROGRESS state to ServiceJobStatus enum and updated string conversion utilities.
- Introduced filterJobCards helper to generalize job filtering by status.
- Updated TechnicianMenu to allow technicians to select job type (Started/Inprogress) and update status accordingly.
- Improved job display to show current status and truncated service names for readability.

Related work items: #1798
2026-06-01 17:25:28 +05:30
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
Avinash Rajesh 34cb64ab1b Add standardized documentation headers 2026-05-22 13:26:02 +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
42 changed files with 4455 additions and 2042 deletions
@@ -233,12 +233,6 @@
<ClInclude Include="models\ComboPackage.h"> <ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter> <Filter>Header Files\Models</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\Config.h"> <ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
@@ -251,5 +245,11 @@
<ClInclude Include="utilities\FileHelper.h"> <ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,13 +1,13 @@
/* /*
File: Controller.cpp File: Controller.cpp
Description: Implementation file containing the method definitions Description: Implementation file containing the method definitions of the
of the Controller class, which manages user authentication, Controller class, including authentication, user creation,
inventory, services, bookings, and notifications. service purchasing, and system checks.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "Controller.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "Controller.h"
#include "Enums.h" #include "Enums.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
@@ -15,15 +15,14 @@ Date:19-May-2026
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "User.h" #include "User.h"
#include "User.h"
#include <stdexcept> #include <stdexcept>
/* /*
Function: login Function: login
Description: Authenticates a user based on provided credentials. Description: Authenticates a user by delegating to the authentication management service.
Parameter: const std::string& username - the username of the user Parameter: const std::string& username - users username
const std::string& password - the password of the user const std::string& password - users password
Return type: bool Return type: bool - true if login successful, false otherwise
*/ */
bool Controller::login(const std::string& username, const std::string& password) bool Controller::login(const std::string& username, const std::string& password)
{ {
@@ -32,8 +31,7 @@ bool Controller::login(const std::string& username, const std::string& password)
/* /*
Function: logout Function: logout
Description: Logs out the currently authenticated user by delegating Description: Logs out the currently authenticated user.
to the authentication management service.
Parameter: None Parameter: None
Return type: void Return type: void
*/ */
@@ -44,9 +42,8 @@ void Controller::logout()
/* /*
Function: changePassword Function: changePassword
Description: Updates the password of the authenticated user by delegating Description: Changes the password of the currently authenticated user.
to the authentication management service. Parameter: const std::string& newPassword - new password to set
Parameter: const std::string& newPassword - the new password to set
Return type: void Return type: void
*/ */
void Controller::changePassword(const std::string& newPassword) void Controller::changePassword(const std::string& newPassword)
@@ -54,11 +51,28 @@ void Controller::changePassword(const std::string& newPassword)
m_authenticationManagementService.changePassword(newPassword); m_authenticationManagementService.changePassword(newPassword);
} }
/*
Function: createCustomer
Description: Creates a new customer account with the provided details.
Parameter: const std::string& username - customers username
const std::string& name - customers name
const std::string& password - customers password
const std::string& email - customers email
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) 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); m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER);
} }
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: const User* - pointer to the authenticated user
*/
const User* Controller::getAuthenticatedUser() const User* Controller::getAuthenticatedUser()
{ {
return m_authenticationManagementService.getAuthenticatedUser(); return m_authenticationManagementService.getAuthenticatedUser();
@@ -79,6 +93,13 @@ void Controller::createTechnician(const std::string& username, const std::string
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN); m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
} }
/*
Function: updateUserDetails
Description: Updates the email and phone details of the currently authenticated user.
Parameter: const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void Controller::updateUserDetails(const std::string& email, const std::string& phone) void Controller::updateUserDetails(const std::string& email, const std::string& phone)
{ {
User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
@@ -89,6 +110,14 @@ void Controller::updateUserDetails(const std::string& email, const std::string&
m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone); 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() util::Map<std::string, const Service*> Controller::getServices()
{ {
util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices(); util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices();
@@ -122,11 +151,29 @@ util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
return readOnlyComboPackages; return readOnlyComboPackages;
} }
/*
Function: purchaseService
Description: Purchases one or more services for a vehicle by delegating to the service management service.
Parameter: const util::Vector<std::string>& serviceIDs - IDs of services to purchase
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
m_serviceManagementService.purchaseService(serviceIDs, vehicleNumber, vehicleBrand, vehicleModel); m_serviceManagementService.purchaseService(serviceIDs, vehicleNumber, vehicleBrand, vehicleModel);
} }
/*
Function: purchaseComboPackage
Description: Purchases a combo package for a vehicle by delegating to the service management service.
Parameter: const std::string& comboPackageID - ID of the combo package
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel); m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
@@ -141,12 +188,12 @@ Return type: util::Map<std::string, const InventoryItem*>
*/ */
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems() util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{ {
auto inventoryIems = m_inventoryManagementService.getInventoryItems(); auto inventoryItems = m_inventoryManagementService.getInventoryItems();
util::Map<std::string, const InventoryItem*> readOnlyInventoryItems; util::Map<std::string, const InventoryItem*> readOnlyInventoryItems;
int inventoryItemsMapSize = inventoryIems.getSize(); int inventoryItemsMapSize = inventoryItems.getSize();
for (int index = 0; index < inventoryItemsMapSize; index++) for (int index = 0; index < inventoryItemsMapSize; index++)
{ {
readOnlyInventoryItems.insert(inventoryIems.getKeyAt(index), inventoryIems.getValueAt(index)); readOnlyInventoryItems.insert(inventoryItems.getKeyAt(index), inventoryItems.getValueAt(index));
} }
return readOnlyInventoryItems; return readOnlyInventoryItems;
} }
@@ -198,6 +245,14 @@ void Controller::addInventoryItemStock(const std::string& selectedItemId, int qu
m_inventoryManagementService.addInventoryItemStock(selectedItemId, 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() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{ {
auto serviceBookings = m_serviceManagementService.getServiceBookings(); auto serviceBookings = m_serviceManagementService.getServiceBookings();
@@ -209,6 +264,14 @@ util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
return readOnlyServiceBookings; 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) util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{ {
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap; util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap;
@@ -238,6 +301,14 @@ util::Map<std::string, const User*> Controller::getUsers()
return readOnlyUserList; 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) util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{ {
auto userMap = m_userManagementService.getUsers(userType); auto userMap = m_userManagementService.getUsers(userType);
@@ -249,21 +320,57 @@ util::Map<std::string, const User*> Controller::getUsers(util::UserType userType
return readOnlyUserMap; 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) void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
m_serviceManagementService.createJobCard(bookingID, technicianID, 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) void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
m_serviceManagementService.createService(name, inventoryItemIDs, 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) void Controller::removeService(const std::string& serviceID)
{ {
m_serviceManagementService.removeService(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() util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{ {
const User* currentUser = getAuthenticatedUser(); const User* currentUser = getAuthenticatedUser();
@@ -277,9 +384,17 @@ util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
return readOnlyJobCardMap; 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.completeJob(jobID); m_serviceManagementService.updateJobStatus(jobID);
} }
/* /*
@@ -294,10 +409,8 @@ void Controller::removeUser(const std::string& userID)
User* user = m_userManagementService.getUser(userID); User* user = m_userManagementService.getUser(userID);
if (!user) if (!user)
{ {
throw std::runtime_error("Error User not Found.\n"); throw std::runtime_error("Error: User not Found.\n");
} }
m_serviceManagementService.cancelCustomerServiceBookings(userID);
m_serviceManagementService.cancelTechnicianJobs(userID);
m_userManagementService.removeUser(userID); m_userManagementService.removeUser(userID);
} }
@@ -327,6 +440,15 @@ void Controller::removeComboPackage(const std::string& comboPackageID)
m_serviceManagementService.removeComboPackage(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() util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
{ {
User* currentUser = m_authenticationManagementService.getAuthenticatedUser(); User* currentUser = m_authenticationManagementService.getAuthenticatedUser();
@@ -340,6 +462,47 @@ util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
return userInvoicesReadOnly; return userInvoicesReadOnly;
} }
/*
Function: getAllInvoices
Description: Retrieves all invoices from the PaymentManagementService and returns them as a read-only map.
Parameters:
- none
Returns:
- util::Map<std::string, const Invoice*>: Map of invoice IDs to invoice objects
*/
util::Map<std::string, const Invoice*> Controller::getAllInvoices()
{
auto invoices = m_paymentManagementService.getAllInvoices();
util::Map<std::string, const Invoice*> readOnlyInvoice;
for (int iterator = 0; iterator < invoices.getSize(); iterator++)
{
readOnlyInvoice.insert(invoices.getKeyAt(iterator), invoices.getValueAt(iterator));
}
return readOnlyInvoice;
}
/*
Function: confirmPayment
Description: Delegates payment confirmation for a given invoice ID to the PaymentManagementService.
Parameters:
- invoiceID: std::string, ID of the invoice to confirm
Returns:
- void
*/
void Controller::confirmPayment(const std::string& invoiceID)
{
m_paymentManagementService.confirmPayment(invoiceID);
}
/*
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) void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{ {
m_paymentManagementService.completePayment(invoiceID, paymentMode); m_paymentManagementService.completePayment(invoiceID, paymentMode);
@@ -423,6 +586,16 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
} }
/*
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() void Controller::loadSystemData()
{ {
m_userManagementService.loadUsers(); m_userManagementService.loadUsers();
@@ -437,6 +610,16 @@ void Controller::loadSystemData()
m_inventoryManagementService.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() void Controller::saveSystemData()
{ {
m_userManagementService.saveUsers(); m_userManagementService.saveUsers();
@@ -453,9 +636,8 @@ void Controller::saveSystemData()
/* /*
Function: runSystemChecks Function: runSystemChecks
Description: Executes system checks including sending low stock alerts Description: Runs system checks to ensure critical configurations, such as verifying admin existence.
and payment reminders. Parameter: None
Parameters: None
Return type: void Return type: void
*/ */
void Controller::runSystemChecks() void Controller::runSystemChecks()
@@ -6,6 +6,7 @@ Description: Header file declaring the Controller class, which manages
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
@@ -39,7 +40,7 @@ public:
void changePassword(const std::string& newPassword); 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); 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(); const User* getAuthenticatedUser();
void createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber); 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); void updateUserDetails(const std::string& email, const std::string& phone);
util::Map<std::string, const Service*> getServices(); util::Map<std::string, const Service*> getServices();
util::Map<std::string, const ComboPackage*> getComboPackages(); util::Map<std::string, const ComboPackage*> getComboPackages();
@@ -58,11 +59,13 @@ public:
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
util::Map<std::string, const JobCard*> getJobCardsByUser(); 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 removeUser(const std::string& userID);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage); void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID); void removeComboPackage(const std::string& comboPackageID);
util::Map<std::string, const Invoice*> getInvoicesByUser(); util::Map<std::string, const Invoice*> getInvoicesByUser();
util::Map<std::string, const Invoice*> getAllInvoices();
void confirmPayment(const std::string& invoiceID);
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
util::Vector<const Notification*> getNotifications(); util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID); void deleteNotification(const std::string& notificationID);
@@ -1 +0,0 @@
Place files here.
@@ -56,6 +56,19 @@ ComboPackage::ComboPackage(const std::string& packageName, double discountPercen
} }
} }
/*
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) 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_id(id),
m_packageName(packageName), m_packageName(packageName),
@@ -212,6 +225,14 @@ void ComboPackage::setState(util::State status)
m_status = 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) static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{ {
int numberOfServices = serviceIDs.getSize(); int numberOfServices = serviceIDs.getSize();
@@ -227,6 +248,14 @@ static std::string getServiceIDsAsString(const util::Vector<std::string>& servic
return 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) static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{ {
util::Vector<std::string> serviceIDs; util::Vector<std::string> serviceIDs;
@@ -239,6 +268,14 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
return serviceIDs; 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::string ComboPackage::serialize() const
{ {
std::ostringstream serializedComboPackage; std::ostringstream serializedComboPackage;
@@ -250,6 +287,16 @@ std::string ComboPackage::serialize() const
return serializedComboPackage.str(); 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) ComboPackage* ComboPackage::deserialize(const std::string& record)
{ {
std::string id, packageName; std::string id, packageName;
@@ -280,6 +327,14 @@ ComboPackage* ComboPackage::deserialize(const std::string& record)
); );
} }
/*
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() std::string ComboPackage::getHeaders()
{ {
return "ID,PackageName,DiscountPercentage,ServiceIDs,Status"; return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
@@ -8,9 +8,9 @@ Date: 19-May-2026
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include "InventoryItem.h"
#include "Factory.h" #include "Factory.h"
#include "StringHelper.h" #include "StringHelper.h"
#include "InventoryItem.h"
int InventoryItem::m_uid = 0; int InventoryItem::m_uid = 0;
@@ -47,6 +47,19 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_status(util::State::ACTIVE), m_status(util::State::ACTIVE),
m_price(price) {} 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) InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status)
: m_id(id), : m_id(id),
m_partName(partName), m_partName(partName),
@@ -191,6 +204,14 @@ void InventoryItem::setState(util::State status)
m_status = 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::string InventoryItem::serialize() const
{ {
std::ostringstream serializedInventoryItem; std::ostringstream serializedInventoryItem;
@@ -202,6 +223,16 @@ std::string InventoryItem::serialize() const
return serializedInventoryItem.str(); 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) InventoryItem* InventoryItem::deserialize(const std::string& record)
{ {
std::string id, partName; std::string id, partName;
@@ -233,6 +264,14 @@ InventoryItem* InventoryItem::deserialize(const std::string& record)
); );
} }
/*
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() std::string InventoryItem::getHeaders()
{ {
return "ID,PartName,Quantity,Price,Status"; return "ID,PartName,Quantity,Price,Status";
@@ -59,8 +59,7 @@ Invoice::Invoice(
ServiceBooking* booking, ServiceBooking* booking,
const util::Timestamp& invoiceDate, const util::Timestamp& invoiceDate,
double laborCost, double laborCost,
const util::Map<std::string, const util::Map<std::string, InventoryItem*>& parts,
InventoryItem*>& parts,
double partsCost, double partsCost,
double discountPercentage, double discountPercentage,
double totalAmount, double totalAmount,
@@ -88,7 +87,6 @@ Invoice::Invoice(
m_partIDs.push_back(partPointers[index]->getId()); m_partIDs.push_back(partPointers[index]->getId());
} }
} }
Invoice::Invoice( Invoice::Invoice(
const std::string& id, const std::string& id,
const std::string& bookingId, const std::string& bookingId,
@@ -122,6 +120,12 @@ Invoice::Invoice(
} }
} }
/*
Function: getId
Description: Retrieves the unique ID of the invoice.
Returns:
- const std::string& representing the invoice ID.
*/
const std::string& Invoice::getId() const const std::string& Invoice::getId() const
{ {
return m_id; return m_id;
@@ -171,6 +175,14 @@ double Invoice::getLaborCost() const
return m_laborCost; return m_laborCost;
} }
/*
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 const util::Vector<std::string>& Invoice::getPartIDs() const
{ {
return m_partIDs; return m_partIDs;
@@ -180,7 +192,7 @@ const util::Vector<std::string>& Invoice::getPartIDs() const
Function: getParts Function: getParts
Description: Retrieves the map of inventory items used in the service. Description: Retrieves the map of inventory items used in the service.
Returns: Returns:
- const util::Map<std::string, InventoryItem*>& representing the parts. - const util::Map<int, InventoryItem*>& representing the parts.
*/ */
const util::Map<std::string, InventoryItem*>& Invoice::getParts() const const util::Map<std::string, InventoryItem*>& Invoice::getParts() const
{ {
@@ -416,6 +428,14 @@ void Invoice::setStatus(util::PaymentStatus status)
m_status = 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) static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
{ {
int numberOfParts = partIDs.getSize(); int numberOfParts = partIDs.getSize();
@@ -431,6 +451,14 @@ static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
return 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) static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString)
{ {
util::Vector<std::string> partIDs; util::Vector<std::string> partIDs;
@@ -443,6 +471,14 @@ static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsSt
return partIDs; 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::string Invoice::serialize() const
{ {
std::ostringstream serializedInvoice; std::ostringstream serializedInvoice;
@@ -460,6 +496,16 @@ std::string Invoice::serialize() const
return serializedInvoice.str(); 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) Invoice* Invoice::deserialize(const std::string& record)
{ {
std::string id, bookingId; std::string id, bookingId;
@@ -512,6 +558,14 @@ Invoice* Invoice::deserialize(const std::string& record)
); );
} }
/*
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() std::string Invoice::getHeaders()
{ {
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status"; return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
@@ -6,6 +6,7 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include "JobCard.h" #include "JobCard.h"
@@ -17,12 +18,10 @@ int JobCard::m_uid = 0;
/* /*
Function: JobCard Function: JobCard
Description: Default constructor that initializes a new job card with a unique ID, Description: Default constructor that initializes a new job card with
null booking, null service, null technician, and default job status. a unique ID and default values.
Parameters: Parameter: None
- None Return type: Constructor
Returns:
- A new JobCard object.
*/ */
JobCard::JobCard() JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)), : m_id("JC" + std::to_string(++m_uid)),
@@ -33,18 +32,19 @@ JobCard::JobCard()
/* /*
Function: JobCard Function: JobCard
Description: Parameterized constructor that initializes a job card with Description: Parameterized constructor that initializes a new job card with a unique ID and specified details.
booking, service, technician, and status details. Parameters:
Parameter: const std::string& bookingId - ID of the booking - bookingId: ID of the associated service booking.
ServiceBooking* booking - pointer to the booking object - booking: Pointer to the ServiceBooking object.
Service* service - pointer to the service object - service: Pointer to the Service object.
const std::string& serviceId - ID of the service - serviceId: ID of the associated service.
const std::string& technicianId - ID of the technician - technicianId: ID of the assigned technician.
User* technician - pointer to the technician object - technician: Pointer to the User object representing the technician.
const util::Timestamp& assignedDate - date when job was assigned - assignedDate: Timestamp of when the job was assigned.
util::ServiceJobStatus status - current status of the job - status: Current status of the job (STARTED/COMPLETED).
const util::Timestamp& completionDate - date when job was completed - completionDate: Timestamp of when the job was completed.
Return type: Constructor Returns:
- A new JobCard object.
*/ */
JobCard::JobCard(const std::string& bookingId, JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
@@ -67,6 +67,22 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status), m_status(status),
m_completionDate(completionDate) {} 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, JobCard::JobCard(const std::string& id,
const std::string& bookingId, const std::string& bookingId,
const std::string& serviceId, const std::string& serviceId,
@@ -183,9 +199,9 @@ const util::Timestamp& JobCard::getAssignedDate() const
/* /*
Function: getStatus Function: getStatus
Description: Retrieves the current status of the job card. Description: Retrieves the current status of the job.
Parameter: None Returns:
Return type: util::ServiceJobStatus - ServiceJobStatus representing the job status.
*/ */
util::ServiceJobStatus JobCard::getStatus() const util::ServiceJobStatus JobCard::getStatus() const
{ {
@@ -309,9 +325,11 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
/* /*
Function: setStatus Function: setStatus
Description: Sets the status of the job card. Description: Sets the current status of the job.
Parameter: util::ServiceJobStatus status - new job status Parameters:
Return type: void - status: New job status value.
Returns:
- void
*/ */
void JobCard::setStatus(util::ServiceJobStatus status) void JobCard::setStatus(util::ServiceJobStatus status)
{ {
@@ -331,6 +349,14 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate)
m_completionDate = 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::string JobCard::serialize() const
{ {
std::ostringstream serializedJobCard; std::ostringstream serializedJobCard;
@@ -344,6 +370,16 @@ std::string JobCard::serialize() const
return serializedJobCard.str(); 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) JobCard* JobCard::deserialize(const std::string& record)
{ {
std::string id, bookingId, serviceId, technicianId; std::string id, bookingId, serviceId, technicianId;
@@ -379,6 +415,14 @@ JobCard* JobCard::deserialize(const std::string& record)
); );
} }
/*
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() std::string JobCard::getHeaders()
{ {
return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate"; return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
@@ -6,11 +6,11 @@ Description: Header file declaring the JobCard class, which represents
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Enums.h" #include "Enums.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "Enums.h"
class ServiceBooking; class ServiceBooking;
class Service; class Service;
@@ -45,6 +45,19 @@ Notification::Notification(const std::string& recipientUserId, User* recipient,
m_message(message), m_message(message),
m_createdAt(createdAt) {} 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) 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_id(id),
m_recipientUserId(recipientUserId), m_recipientUserId(recipientUserId),
@@ -204,6 +217,14 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt)
m_createdAt = 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::string Notification::serialize() const
{ {
std::ostringstream serializedNotification; std::ostringstream serializedNotification;
@@ -215,6 +236,16 @@ std::string Notification::serialize() const
return serializedNotification.str(); 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) Notification* Notification::deserialize(const std::string& record)
{ {
std::string id, recipientUserId, title, message, createdAtTimestampString; std::string id, recipientUserId, title, message, createdAtTimestampString;
@@ -242,6 +273,14 @@ Notification* Notification::deserialize(const std::string& record)
); );
} }
/*
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() std::string Notification::getHeaders()
{ {
return "ID,RecipientID,Title,Message,Timestamp"; return "ID,RecipientID,Title,Message,Timestamp";
@@ -54,6 +54,19 @@ Service::Service(const std::string& name, const util::Map<std::string, Inventory
} }
} }
/*
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) 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_id(id),
m_name(name), m_name(name),
@@ -90,6 +103,14 @@ const std::string& Service::getName() const
return m_name; 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 const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const
{ {
return m_requiredInventoryItemIDs; return m_requiredInventoryItemIDs;
@@ -200,6 +221,14 @@ void Service::setState(util::State status)
m_status = 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) static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds)
{ {
int numberOfInventoryItems = inventoryItemIds.getSize(); int numberOfInventoryItems = inventoryItemIds.getSize();
@@ -215,6 +244,14 @@ static std::string getInventoryItemIDsAsString(const util::Vector<std::string>&
return 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) static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString)
{ {
util::Vector<std::string> inventoryItemIDs; util::Vector<std::string> inventoryItemIDs;
@@ -227,6 +264,14 @@ static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string&
return inventoryItemIDs; 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::string Service::serialize() const
{ {
std::ostringstream serializedService; std::ostringstream serializedService;
@@ -238,6 +283,16 @@ std::string Service::serialize() const
return serializedService.str(); 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) Service* Service::deserialize(const std::string& record)
{ {
std::string id, name; std::string id, name;
@@ -268,6 +323,14 @@ Service* Service::deserialize(const std::string& record)
); );
} }
/*
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() std::string Service::getHeaders()
{ {
return "ID,Name,InventoryIDs,LaborCost,Status"; return "ID,Name,InventoryIDs,LaborCost,Status";
@@ -20,31 +20,31 @@ int ServiceBooking::m_uid = 0;
Function: ServiceBooking Function: ServiceBooking
Description: Default constructor that initializes a new service booking with a unique ID, Description: Default constructor that initializes a new service booking with a unique ID,
null customer, and zero discount percentage. null customer, and zero discount percentage.
Parameters: Parameters: None
- None Returns: A new ServiceBooking object.
Returns:
- A new ServiceBooking object.
*/ */
ServiceBooking::ServiceBooking() ServiceBooking::ServiceBooking()
: m_id("SRV" + std::to_string(++m_uid)), : m_id("SBK" + std::to_string(++m_uid)),
m_customer(nullptr), m_customer(nullptr),
m_assignedTechnician(nullptr), m_assignedTechnician(nullptr),
m_status(util::ServiceJobStatus::PENDING),
m_discountPercentage(0.0) {} m_discountPercentage(0.0) {}
/* /*
Function: ServiceBooking Function: ServiceBooking
Description: Parameterized constructor that initializes a service booking Description: Parameterized constructor that initializes a new service booking with a unique ID and specified details.
with customer, vehicle, technician, and discount details. Parameters:
Parameter: const std::string& id - booking ID - id: Booking ID string.
util::ServiceJobStatus status - current booking status - status: Current status of the booking (e.g., PENDING, COMPLETED).
const util::Map<std::string, Service*>& services - map of services - services: Map of services included in the booking.
const std::string& customerId - ID of the customer - customerId: ID of the customer.
User* customer - pointer to the customer object - customer: Pointer to the User object representing the customer.
const std::string& vehicleNumber - vehicle registration number - vehicleNumber: Vehicle registration number.
const std::string& vehicleBrand - brand of the vehicle - vehicleBrand: Brand of the vehicle.
const std::string& vehicleModel - model of the vehicle - vehicleModel: Model of the vehicle.
double discountPercentage - discount applied to the booking - discountPercentage: Discount applied to the booking.
Return type: Constructor Returns:
- A new ServiceBooking object.
*/ */
ServiceBooking::ServiceBooking( ServiceBooking::ServiceBooking(
util::ServiceJobStatus status, util::ServiceJobStatus status,
@@ -57,7 +57,7 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleModel, const std::string& vehicleModel,
double discountPercentage double discountPercentage
) )
: m_id("SRV" + std::to_string(++m_uid)), : m_id("SBK" + std::to_string(++m_uid)),
m_status(status), m_status(status),
m_services(services), m_services(services),
m_customerId(customerId), m_customerId(customerId),
@@ -77,6 +77,24 @@ ServiceBooking::ServiceBooking(
} }
} }
/*
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( ServiceBooking::ServiceBooking(
const std::string& id, const std::string& id,
util::ServiceJobStatus status, util::ServiceJobStatus status,
@@ -107,6 +125,12 @@ ServiceBooking::ServiceBooking(
} }
} }
/*
Function: getId
Description: Retrieves the unique identifier of the service booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getId() const const std::string& ServiceBooking::getId() const
{ {
return m_id; return m_id;
@@ -115,14 +139,22 @@ const std::string& ServiceBooking::getId() const
/* /*
Function: getStatus Function: getStatus
Description: Retrieves the current status of the service booking. Description: Retrieves the current status of the service booking.
Returns: Parameter: None
- util::ServiceJobStatus representing the booking status. Return type: util::ServiceJobStatus
*/ */
util::ServiceJobStatus ServiceBooking::getStatus() const util::ServiceJobStatus ServiceBooking::getStatus() const
{ {
return m_status; 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 const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
{ {
return m_serviceIDs; return m_serviceIDs;
@@ -130,9 +162,15 @@ const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
/* /*
Function: getServices Function: getServices
Description: Retrieves the map of services included in the booking. Description: Retrieves the services associated with the booking.
Returns: Parameter: None
- const util::Map<std::string, Service*>& representing the services. Return type: const util::Map<std::string, Service*>&
*/
/*
Function: getServices
Description: Retrieves the services associated with the booking.
Parameter: None
Return type: const util::Map<std::string, Service*>&
*/ */
const util::Map<std::string, Service*>& ServiceBooking::getServices() const const util::Map<std::string, Service*>& ServiceBooking::getServices() const
{ {
@@ -142,8 +180,8 @@ const util::Map<std::string, Service*>& ServiceBooking::getServices() const
/* /*
Function: getCustomerId Function: getCustomerId
Description: Retrieves the customer ID associated with the booking. Description: Retrieves the customer ID associated with the booking.
Returns: Parameter: None
- const std::string& representing the customer ID. Return type: const std::string&
*/ */
const std::string& ServiceBooking::getCustomerId() const const std::string& ServiceBooking::getCustomerId() const
{ {
@@ -152,9 +190,9 @@ const std::string& ServiceBooking::getCustomerId() const
/* /*
Function: getCustomer Function: getCustomer
Description: Retrieves the pointer to the associated customer. Description: Retrieves the customer object associated with the booking.
Returns: Parameter: None
- User* representing the customer. Return type: User*
*/ */
User* ServiceBooking::getCustomer() const User* ServiceBooking::getCustomer() const
{ {
@@ -163,9 +201,9 @@ User* ServiceBooking::getCustomer() const
/* /*
Function: getVehicleNumber Function: getVehicleNumber
Description: Retrieves the vehicle registration number. Description: Retrieves the vehicle registration number for the booking.
Returns: Parameter: None
- const std::string& representing the vehicle number. Return type: const std::string&
*/ */
const std::string& ServiceBooking::getVehicleNumber() const const std::string& ServiceBooking::getVehicleNumber() const
{ {
@@ -174,9 +212,9 @@ const std::string& ServiceBooking::getVehicleNumber() const
/* /*
Function: getVehicleBrand Function: getVehicleBrand
Description: Retrieves the brand of the vehicle. Description: Retrieves the brand of the vehicle for the booking.
Returns: Parameter: None
- const std::string& representing the vehicle brand. Return type: const std::string&
*/ */
const std::string& ServiceBooking::getVehicleBrand() const const std::string& ServiceBooking::getVehicleBrand() const
{ {
@@ -185,9 +223,9 @@ const std::string& ServiceBooking::getVehicleBrand() const
/* /*
Function: getVehicleModel Function: getVehicleModel
Description: Retrieves the model of the vehicle. Description: Retrieves the model of the vehicle for the booking.
Returns: Parameter: None
- const std::string& representing the vehicle model. Return type: const std::string&
*/ */
const std::string& ServiceBooking::getVehicleModel() const const std::string& ServiceBooking::getVehicleModel() const
{ {
@@ -196,9 +234,9 @@ const std::string& ServiceBooking::getVehicleModel() const
/* /*
Function: getAssignedTechnicianId Function: getAssignedTechnicianId
Description: Retrieves the ID of the assigned technician. Description: Retrieves the ID of the technician assigned to the booking.
Returns: Parameter: None
- const std::string& representing the technician ID. Return type: const std::string&
*/ */
const std::string& ServiceBooking::getAssignedTechnicianId() const const std::string& ServiceBooking::getAssignedTechnicianId() const
{ {
@@ -215,12 +253,11 @@ User* ServiceBooking::getAssignedTechnician() const
{ {
return m_assignedTechnician; return m_assignedTechnician;
} }
/* /*
Function: getDiscountPercentage Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the booking. Description: Retrieves the discount percentage applied to the booking.
Returns: Parameter: None
- double representing the discount percentage. Return type: double
*/ */
double ServiceBooking::getDiscountPercentage() const double ServiceBooking::getDiscountPercentage() const
{ {
@@ -229,11 +266,9 @@ double ServiceBooking::getDiscountPercentage() const
/* /*
Function: setId Function: setId
Description: Sets the unique ID of the service booking. Description: Sets the unique identifier of the service booking.
Parameters: Parameter: const std::string& id - new booking ID
- id: New booking ID string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setId(const std::string& id) void ServiceBooking::setId(const std::string& id)
{ {
@@ -243,10 +278,8 @@ void ServiceBooking::setId(const std::string& id)
/* /*
Function: setStatus Function: setStatus
Description: Sets the current status of the service booking. Description: Sets the current status of the service booking.
Parameters: Parameter: const util::ServiceJobStatus& status - new booking status
- status: New booking status value. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setStatus(const util::ServiceJobStatus& status) void ServiceBooking::setStatus(const util::ServiceJobStatus& status)
{ {
@@ -255,11 +288,9 @@ void ServiceBooking::setStatus(const util::ServiceJobStatus& status)
/* /*
Function: setServices Function: setServices
Description: Sets the services included in the booking. Description: Sets the services associated with the booking.
Parameters: Parameter: const util::Map<std::string, Service*>& services - new services map
- services: Map of services. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setServices(const util::Map<std::string, Service*>& services) void ServiceBooking::setServices(const util::Map<std::string, Service*>& services)
{ {
@@ -275,11 +306,9 @@ void ServiceBooking::setServices(const util::Map<std::string, Service*>& service
/* /*
Function: setCustomerId Function: setCustomerId
Description: Sets the customer ID associated with the booking. Description: Sets the customer ID for the booking.
Parameters: Parameter: const std::string& customerId - new customer ID
- customerId: New customer ID string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setCustomerId(const std::string& customerId) void ServiceBooking::setCustomerId(const std::string& customerId)
{ {
@@ -288,11 +317,9 @@ void ServiceBooking::setCustomerId(const std::string& customerId)
/* /*
Function: setCustomer Function: setCustomer
Description: Sets the pointer to the associated customer. Description: Sets the customer object for the booking.
Parameters: Parameter: User* customer - pointer to the customer object
- customer: Pointer to the User object. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setCustomer(User* customer) void ServiceBooking::setCustomer(User* customer)
{ {
@@ -301,11 +328,9 @@ void ServiceBooking::setCustomer(User* customer)
/* /*
Function: setVehicleNumber Function: setVehicleNumber
Description: Sets the vehicle registration number. Description: Sets the vehicle registration number for the booking.
Parameters: Parameter: const std::string& vehicleNumber - new vehicle number
- vehicleNumber: New vehicle number string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber) void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber)
{ {
@@ -314,11 +339,9 @@ void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber)
/* /*
Function: setVehicleBrand Function: setVehicleBrand
Description: Sets the brand of the vehicle. Description: Sets the brand of the vehicle for the booking.
Parameters: Parameter: const std::string& vehicleBrand - new vehicle brand
- vehicleBrand: New vehicle brand string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand) void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand)
{ {
@@ -327,11 +350,9 @@ void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand)
/* /*
Function: setVehicleModel Function: setVehicleModel
Description: Sets the model of the vehicle. Description: Sets the model of the vehicle for the booking.
Parameters: Parameter: const std::string& vehicleModel - new vehicle model
- vehicleModel: New vehicle model string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setVehicleModel(const std::string& vehicleModel) void ServiceBooking::setVehicleModel(const std::string& vehicleModel)
{ {
@@ -340,11 +361,9 @@ void ServiceBooking::setVehicleModel(const std::string& vehicleModel)
/* /*
Function: setAssignedTechnicianId Function: setAssignedTechnicianId
Description: Sets the ID of the assigned technician. Description: Sets the ID of the technician assigned to the booking.
Parameters: Parameter: const std::string& assignedTechnicianId - new technician ID
- assignedTechnicianId: New technician ID string. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId) void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId)
{ {
@@ -364,17 +383,23 @@ void ServiceBooking::setAssignedTechnician(User* assignedTechnician)
/* /*
Function: setDiscountPercentage Function: setDiscountPercentage
Description: Sets the discount percentage applied to the booking. Description: Sets the discount percentage for the booking.
Parameters: Parameter: double discountPercentage - new discount percentage
- discountPercentage: New discount percentage value. Return type: void
Returns:
- void
*/ */
void ServiceBooking::setDiscountPercentage(double discountPercentage) void ServiceBooking::setDiscountPercentage(double discountPercentage)
{ {
m_discountPercentage = 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) static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{ {
int numberOfServices = serviceIDs.getSize(); int numberOfServices = serviceIDs.getSize();
@@ -390,6 +415,14 @@ static std::string getServiceIDsAsString(const util::Vector<std::string>& servic
return 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) static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{ {
util::Vector<std::string> serviceIDs; util::Vector<std::string> serviceIDs;
@@ -402,6 +435,14 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
return serviceIDs; 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::string ServiceBooking::serialize() const
{ {
std::ostringstream serializedBooking; std::ostringstream serializedBooking;
@@ -417,6 +458,16 @@ std::string ServiceBooking::serialize() const
return serializedBooking.str(); 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) ServiceBooking* ServiceBooking::deserialize(const std::string& record)
{ {
std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId; std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
@@ -455,6 +506,14 @@ ServiceBooking* ServiceBooking::deserialize(const std::string& record)
); );
} }
/*
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() std::string ServiceBooking::getHeaders()
{ {
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage"; return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
@@ -53,6 +53,22 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role), m_type(role),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {}
/*
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) 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_id(userId),
m_userName(userName), m_userName(userName),
@@ -306,6 +322,14 @@ void User::setState(util::State status)
m_status = status; m_status = status;
} }
/*
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::string User::serialize() const
{ {
std::ostringstream serializedUser; std::ostringstream serializedUser;
@@ -320,6 +344,14 @@ std::string User::serialize() const
return serializedUser.str(); 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) User* User::deserialize(const std::string& record)
{ {
std::string id, name, username, phone, password, email; std::string id, name, username, phone, password, email;
@@ -345,8 +377,15 @@ User* User::deserialize(const std::string& record)
status); 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() std::string User::getHeaders()
{ {
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus"; return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
} }
@@ -6,12 +6,22 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "User.h" #include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr; User* AuthenticationManagementService::m_authenticatedUser = nullptr;
/*
Function: login
Description: Authenticates a user by checking the provided username and password
against the stored users in the DataStore. If successful, sets the
authenticated user.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool AuthenticationManagementService::login(const std::string& username, const std::string& password) bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{ {
util::Map<std::string, User*> users = m_dataStore.getUsers(); util::Map<std::string, User*> users = m_dataStore.getUsers();
@@ -32,6 +42,12 @@ bool AuthenticationManagementService::login(const std::string& username, const s
return false; return false;
} }
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: User* - pointer to the authenticated user
*/
User* AuthenticationManagementService::getAuthenticatedUser() User* AuthenticationManagementService::getAuthenticatedUser()
{ {
return m_authenticatedUser; return m_authenticatedUser;
@@ -6,6 +6,7 @@ Description: Header file declaring the AuthenticationManagementService class, wh
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "DataStore.h" #include "DataStore.h"
@@ -1,25 +1,184 @@
/* /*
File: InventoryManagementService.cpp File: InventoryManagementService.cpp
Description: Implementation file containing the method definitions of the Description: Implements the InventoryManagementService class, which manages inventory
InventoryManagementService class, including inventory operations items and observer relationships within the system. Provides methods
and notification handling. for loading and saving inventory items from persistent storage, as well
as attaching and persisting observers for notification handling.
Author: Trenser Author: Trenser
Date:19-May-2026 Date: 22-May-2026
*/ */
#include "InventoryManagementService.h"
#include <stdexcept>
#include "Config.h" #include "Config.h"
#include "Vector.h"
#include "Enums.h" #include "Enums.h"
#include "InventoryItem.h"
#include "Config.h"
#include "User.h"
#include "Factory.h" #include "Factory.h"
#include "Timestamp.h"
#include "FileManager.h" #include "FileManager.h"
#include "InventoryItem.h"
#include "InventoryManagementService.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h" #include "Utility.h"
#include "Vector.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{}; 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 Function: addInventoryItem
Description: Creates a new inventory item using the Factory and inserts it Description: Creates a new inventory item using the Factory and inserts it
@@ -102,6 +261,14 @@ InventoryItem* InventoryManagementService::getInventoryItem(const std::string& i
return nullptr; 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) void InventoryManagementService::attach(User* user)
{ {
if (user) if (user)
@@ -114,6 +281,14 @@ void InventoryManagementService::attach(User* 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) void InventoryManagementService::detach(User* user)
{ {
if (user) if (user)
@@ -126,6 +301,18 @@ void InventoryManagementService::detach(User* user)
} }
} }
/*
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) void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{ {
if (user) if (user)
@@ -136,7 +323,7 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
Factory::getObject<Notification>( Factory::getObject<Notification>(
user->getId(), user->getId(),
user, user,
"InventoryManagementService: " + title, title,
message, message,
util::Timestamp() util::Timestamp()
); );
@@ -152,94 +339,3 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
} }
} }
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{
int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++)
{
inventoryManagementService.sendNotification(
adminUsers[index],
"Low Stock Alert",
"The inventory item with ID " + inventoryItem->getId() +
" has very low quantity in the inventory"
);
}
}
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);
}
}
}
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;
}
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);
}
}
void InventoryManagementService::saveInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
inventoryItemFileManager.save(inventoryItems);
}
void InventoryManagementService::loadObservers()
{
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
}
void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
@@ -6,6 +6,7 @@ Description: Header file declaring the InventoryManagementService class,
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -8,7 +8,6 @@ Date: 20-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "PaymentManagementService.h"
#include "Config.h" #include "Config.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h" #include "Factory.h"
@@ -16,6 +15,7 @@ Date: 20-May-2026
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "JobCard.h" #include "JobCard.h"
#include "PaymentManagementService.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
@@ -24,90 +24,6 @@ Date: 20-May-2026
util::Map<std::string, User*> PaymentManagementService::m_observers{}; util::Map<std::string, User*> PaymentManagementService::m_observers{};
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);
}
}
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
{
if (!booking)
{
throw std::runtime_error("Invoice generation failed: booking is null.");
}
double totalLabourCost = 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);
if (currentJobCard->getBookingId() == bookingID && currentJobCard->getStatus() != 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);
totalLabourCost += currentService->getLaborCost();
totalPartsCost += util::calculatePartsCost(currentService);
}
}
totalServiceCost = totalLabourCost + totalPartsCost;
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLabourCost, 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);
}
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;
}
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);
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.");
}
}
/* /*
Function: attach Function: attach
Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications. Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications.
@@ -170,7 +86,7 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t
Factory::getObject<Notification>( Factory::getObject<Notification>(
user->getId(), user->getId(),
user, user,
"PaymentManagementService: " + title, title,
message, message,
util::Timestamp() util::Timestamp()
); );
@@ -214,9 +130,9 @@ void PaymentManagementService::sendPaymentReminders()
User* customer = serviceBooking->getCustomer(); User* customer = serviceBooking->getCustomer();
if (customer) if (customer)
{ {
sendNotification(customer, std::string title = "Payment Reminder";
"Payment Reminder", std::string message = "Your payment for Invoice ID " + invoice->getId() + " is still pending. Please complete the payment.";
"Your payment for Invoice ID " + invoice->getId() + " is still pending.Please complete the payment." + invoice->getId()); sendNotification(customer, title, message);
} }
} }
} }
@@ -224,6 +140,15 @@ void PaymentManagementService::sendPaymentReminders()
} }
} }
/*
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> PaymentManagementService::getObserverIDs()
{ {
util::Vector<std::string> observerIDs; util::Vector<std::string> observerIDs;
@@ -239,6 +164,19 @@ util::Vector<std::string> PaymentManagementService::getObserverIDs()
return observerIDs; 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() void PaymentManagementService::loadInvoices()
{ {
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE); util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
@@ -272,6 +210,16 @@ void PaymentManagementService::loadInvoices()
invoices[invoice->getId()] = invoice; 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() void PaymentManagementService::saveInvoices()
{ {
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE); util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
@@ -279,12 +227,205 @@ void PaymentManagementService::saveInvoices()
invoiceFileManager.save(invoices); 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() void PaymentManagementService::loadObservers()
{ {
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore); 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() void PaymentManagementService::saveObservers()
{ {
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); 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::PAID)
{
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentMethod(paymentMode);
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::PAID);
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.");
}
}
/*
Function: getAllInvoice
Description: Provides access to all invoices stored in the data store.
Parameters:
- none
Returns:
- util::Map<std::string, Invoice*>&: Map of invoice IDs to invoice objects
*/
util::Map<std::string, Invoice*>& PaymentManagementService::getAllInvoices()
{
return m_dataStore.getInvoices();
}
/*
Function: confirmPayment
Description: Confirms payment for a specific invoice. Updates payment date and status,
then sends a notification to the customer.
Parameters:
- invoiceID: std::string, ID of the invoice to confirm
Returns:
- void
Throws:
- std::runtime_error if the invoice ID is invalid
*/
void PaymentManagementService::confirmPayment(const std::string& invoiceID)
{
auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex == -1)
{
throw std::runtime_error("Payment confirmation failed: invalid invoice ID.");
}
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID)
{
throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation.");
}
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setStatus(util::PaymentStatus::COMPLETED);
std::string title = "Payment Confirmed";
std::string message = "Payment Confirmed for Invoice ID " + invoiceID;
sendNotification(currentUser, title, message);
}
@@ -28,6 +28,8 @@ public:
void generateInvoice(ServiceBooking* booking); void generateInvoice(ServiceBooking* booking);
util::Map<std::string, Invoice*> getInvoices(const std::string& customerID); util::Map<std::string, Invoice*> getInvoices(const std::string& customerID);
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
util::Map<std::string, Invoice*>& getAllInvoices();
void confirmPayment(const std::string& invoiceID);
void sendPaymentReminders(); void sendPaymentReminders();
void sendNotification(User* user, const std::string& title, const std::string& message) override; void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override; void attach(User* user) override;
@@ -6,6 +6,7 @@ Description: Header file declaring the ServiceManagementService class, which man
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -36,7 +37,7 @@ public:
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID); 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 cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID); void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage); void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage);
@@ -1,7 +1,8 @@
/* /*
File: UserManagementService.cpp File: UserManagementService.cpp
Description: Implementation file containing the method definitions of the Description: Implementation file containing the method definitions of the
UserManagementService class, including user retrieval and removal logic. UserManagementService class, including user creation, updates,
and ensuring an admin account exists.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
@@ -12,14 +13,22 @@ Date:19-May-2026
#include "Factory.h" #include "Factory.h"
#include "FileManager.h" #include "FileManager.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Invoice.h" #include "Notification.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include "Validator.h"
/*
Function: ensureAdminExists
Description: Ensures that at least one admin user exists in the system.
If no admin is found, creates a default admin user using
configuration constants.
Parameter: None
Return type: void
*/
void UserManagementService::ensureAdminExists() void UserManagementService::ensureAdminExists()
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
@@ -46,22 +55,37 @@ void UserManagementService::ensureAdminExists()
} }
} }
/*
Function: createUser
Description: Creates a new user with the provided details. Validates that
the username is unique, then attaches the user to relevant
management services (payment, service, inventory).
Parameter: const std::string& username - users username
const std::string& name - users name
const std::string& password - users password
const std::string& email - users email address
const std::string& phone - users phone number
util::UserType type - type of user (ADMIN, CUSTOMER, TECHNICIAN)
Return type: void
*/
void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type) void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type)
{ {
InventoryManagementService inventoryManagementService; InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService; ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
int index = usersMap.findIf( if (util::isUsernameDuplicate(username, usersMap))
[&](const std::string&, User* user)
{
return user->getUserName() == username;
}
);
if (index != -1)
{ {
throw std::runtime_error("Username already exists"); 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); User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser); usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser); paymentManagementService.attach(newUser);
@@ -72,80 +96,42 @@ void UserManagementService::createUser(const std::string& username, const std::s
} }
} }
/*
Function: updateUserDetails
Description: Updates the email and phone details of an existing user.
Throws an exception if the user does not exist.
Parameter: const std::string& userID - ID of the user to update
const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
int index = usersMap.find(userID); int index = usersMap.find(userID);
if (index == -1) 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); 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->setEmail(email);
user->setPhone(phone); user->setPhone(phone);
} }
/*
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();
}
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->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
/*
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)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
user->setState(util::State::INACTIVE);
}
}
}
/* /*
Function: getUserNotifications Function: getUserNotifications
Description: Retrieves all notifications associated with a given user ID. Description: Retrieves all notifications associated with a given user ID.
@@ -208,6 +194,18 @@ void UserManagementService::deleteNotification(const std::string& notificationID
notifications.remove(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() void UserManagementService::loadUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -235,6 +233,15 @@ void UserManagementService::loadUsers()
} }
} }
/*
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() void UserManagementService::saveUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -254,3 +261,78 @@ void UserManagementService::saveUsers()
userFileManager.save(users); userFileManager.save(users);
notificationFileManager.save(notifications); 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;
}
@@ -1,7 +1,8 @@
/* /*
File: UserManagementService.h File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, and notification handling. user creation, updates, retrieval, removal, notifications, and ensures
the existence of an admin account.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
@@ -1,7 +1,8 @@
/* /*
File: Config.h File: Config.h
Description: Defines configuration constants for system thresholds in the Vehicle Service Management System. Description: Header file declaring configuration constants for the Vehicle Service System.
Includes limits for inventory stock alerts and payment reminder intervals. Includes default admin account details such as username, name, password,
email, and phone number.
Author: Trenser Author: Trenser
Date: 21-May-2026 Date: 21-May-2026
*/ */
@@ -29,7 +29,8 @@ namespace util
enum class PaymentStatus enum class PaymentStatus
{ {
PENDING, PENDING,
COMPLETED COMPLETED,
PAID
}; };
enum class ServiceJobStatus enum class ServiceJobStatus
@@ -37,6 +38,7 @@ namespace util
PENDING, PENDING,
STARTED, STARTED,
COMPLETED, COMPLETED,
IN_PROGRESS,
CANCELLED CANCELLED
}; };
@@ -137,6 +139,10 @@ namespace util
{ {
return PaymentMode::OFFLINE; return PaymentMode::OFFLINE;
} }
if (value == "NOTSET")
{
return PaymentMode::NOTSET;
}
throw std::invalid_argument("Invalid PaymentMode string"); throw std::invalid_argument("Invalid PaymentMode string");
} }
@@ -156,6 +162,8 @@ namespace util
return "PENDING"; return "PENDING";
case PaymentStatus::COMPLETED: case PaymentStatus::COMPLETED:
return "COMPLETED"; return "COMPLETED";
case PaymentStatus::PAID:
return "PAID";
} }
throw std::invalid_argument("Invalid PaymentStatus"); throw std::invalid_argument("Invalid PaymentStatus");
} }
@@ -205,6 +213,8 @@ namespace util
return "COMPLETED"; return "COMPLETED";
case ServiceJobStatus::CANCELLED: case ServiceJobStatus::CANCELLED:
return "CANCELLED"; return "CANCELLED";
case ServiceJobStatus::IN_PROGRESS:
return "IN_PROGRESS";
} }
throw std::invalid_argument("Invalid ServiceJobStatus"); throw std::invalid_argument("Invalid ServiceJobStatus");
} }
@@ -237,6 +247,10 @@ namespace util
{ {
return ServiceJobStatus::CANCELLED; return ServiceJobStatus::CANCELLED;
} }
if (value == "IN_PROGRESS")
{
return ServiceJobStatus::IN_PROGRESS;
}
throw std::invalid_argument("Invalid ServiceJobStatus string"); throw std::invalid_argument("Invalid ServiceJobStatus string");
} }
@@ -1,17 +1,67 @@
/*
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 #pragma once
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <direct.h>
#include "Vector.h" #include "Vector.h"
namespace util 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) inline util::Vector<std::string> loadRecords(const std::string& filePath)
{ {
util::Vector<std::string> records; util::Vector<std::string> records;
std::ifstream file(filePath); std::ifstream file(filePath);
if (!file.is_open()) if (!file.is_open())
{ {
ensureDirectoryExists(filePath);
std::ofstream newFile(filePath); std::ofstream newFile(filePath);
newFile.close(); newFile.close();
file.open(filePath); file.open(filePath);
@@ -30,6 +80,18 @@ namespace util
return records; 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) inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{ {
std::ofstream file(filePath, std::ios::trunc); std::ofstream file(filePath, std::ios::trunc);
@@ -1,9 +1,21 @@
/*
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 #pragma once
#include <string>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <fstream> #include <fstream>
#include "Vector.h" #include "Vector.h"
#include "Map.h" #include "Map.h"
#include "FileHelper.h"
namespace util namespace util
{ {
@@ -21,6 +33,18 @@ namespace util
void save(const objects<T>&); 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> template <typename T>
objects<T> FileManager<T>::load() objects<T> FileManager<T>::load()
{ {
@@ -28,6 +52,7 @@ namespace util
std::ifstream file(m_filePath); std::ifstream file(m_filePath);
if (!file.is_open()) if (!file.is_open())
{ {
ensureDirectoryExists(m_filePath);
std::ofstream newFile(m_filePath); std::ofstream newFile(m_filePath);
newFile.close(); newFile.close();
file.open(m_filePath); file.open(m_filePath);
@@ -58,6 +83,17 @@ namespace util
return records; 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> template <typename T>
void FileManager<T>::save(const objects<T>& records) void FileManager<T>::save(const objects<T>& records)
{ {
@@ -62,6 +62,7 @@ namespace util
*/ */
inline void pressEnter() inline void pressEnter()
{ {
std::cout << std::endl;
system("pause"); system("pause");
} }
} }
@@ -21,4 +21,28 @@ namespace util
{ {
std::cout << "\x1B[2J\x1B[H" << std::flush; 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) + "...";
}
} }
@@ -1,8 +1,26 @@
/*
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 <cctype>
#include <string> #include <string>
namespace util 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) inline int extractNumber(const std::string& input)
{ {
int result = 0; int result = 0;
@@ -1,17 +1,17 @@
/* /*
File: Utility.h File: Utility.h
Description: Header file declaring utility functions used across the system, Description: Header file declaring utility functions used across the system
including cost calculation for services based on required inventory items.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Service.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "DataStore.h"
#include "FileHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "NotificationManagementService.h" #include "NotificationManagementService.h"
#include "FileHelper.h" #include "Service.h"
#include "DataStore.h"
namespace util namespace util
{ {
@@ -37,11 +37,9 @@ namespace util
/* /*
Function: calculateComboServiceEstimatedCost Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing Description: Calculates the estimated total cost of a combo package by summing
the labor cost and parts cost of all services included in the package. the labor and parts costs of all services included in the package.
Parameters: Parameter: const ComboPackage* comboPackage - pointer to the combo package object
- comboPackage: const ComboPackage*, pointer to the combo package whose cost is to be estimated Return type: double - estimated total cost of the combo package
Returns:
- double: The estimated total cost of the combo package
*/ */
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage) inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{ {
@@ -56,6 +54,20 @@ namespace util
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) inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
{ {
auto observerIDs = util::loadRecords(filePath); auto observerIDs = util::loadRecords(filePath);
@@ -72,6 +84,16 @@ namespace util
} }
} }
/*
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) inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
{ {
auto observerIDs = service->getObserverIDs(); auto observerIDs = service->getObserverIDs();
@@ -107,3 +107,69 @@ bool util::isPasswordValid(const std::string& password)
return hasUpper && hasLower && hasDigit && hasSpecial; 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<string>
#include<algorithm> #include<algorithm>
#include<cctype> #include<cctype>
#include "Map.h"
#include "User.h"
namespace util namespace util
{ {
bool isPhoneNumberValid(const std::string&); bool isPhoneNumberValid(const std::string&);
bool isEmailValid(const std::string&); bool isEmailValid(const std::string&);
bool isPasswordValid(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*>&);
} }
File diff suppressed because it is too large Load Diff
@@ -6,6 +6,7 @@ Description: Header file declaring the AdminMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -23,10 +24,14 @@ public:
void removeInventoryItem(); void removeInventoryItem();
void checkStockAvailability(); void checkStockAvailability();
void assignJob(); void assignJob();
void displayServices();
void createService(); void createService();
void removeService(); void removeService();
void displayUsers();
void confirmPayment();
void addTechnician(); void addTechnician();
void removeUser(); void removeUser();
void displayComboPackages();
void createComboPackages(); void createComboPackages();
void removeComboPackage(); void removeComboPackage();
void viewNotifications(); void viewNotifications();
@@ -1,41 +1,36 @@
/* /*
File: CustomerMenu.cpp File: CustomerMenu.cpp
Description: Implements the CustomerMenu class which provides the customers console interface Description: Implementation file containing the method definitions of the
in the Vehicle Service Management System. Handles menu display, user input, and CustomerMenu class, including menu handling, service selection,
customer-specific operations such as booking services, viewing history, managing payments, combo package booking, profile updates, and password management.
invoices, and notifications.
Author: Trenser Author: Trenser
Date: 19-May-2026 Date:19-May-2026
*/ */
#include <iomanip> #include <iomanip>
#include <iostream>
#include "ComboPackage.h" #include "ComboPackage.h"
#include "CustomerMenu.h" #include "CustomerMenu.h"
#include "MenuHelper.h"
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "Map.h" #include "Map.h"
#include "MenuHelper.h"
#include "OutputHelper.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
#include "Utility.h"
#include "Validator.h" #include "Validator.h"
#include "Vector.h" #include "Vector.h"
/* /*
Function: showMenu Function: showMenu
Description: Displays the customer menu in a loop until the user chooses to logout. Description: Displays the customer menu and handles user input until logout is selected.
Handles exceptions and ensures smooth user interaction. Parameter: None
Parameters: Return type: void
- None
Returns:
- void
*/ */
void CustomerMenu::showMenu() void CustomerMenu::showMenu()
{ {
while (true) while (true)
@@ -70,6 +65,12 @@ void CustomerMenu::showMenu()
} }
} }
/*
Function: handleOperation
Description: Executes the corresponding customer operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool CustomerMenu::handleOperation(int choice) bool CustomerMenu::handleOperation(int choice)
{ {
switch (choice) switch (choice)
@@ -111,37 +112,44 @@ bool CustomerMenu::handleOperation(int choice)
return true; return true;
} }
/*
Function: logout
Description: Logs out the currently authenticated customer user.
Parameter: None
Return type: void
*/
void CustomerMenu::logout() void CustomerMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/*
Function: changePassword
Description: Allows the customer to change their password after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::changePassword() void CustomerMenu::changePassword()
{ {
std::string newPassword; changePasswordHelper(m_controller);
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();
} }
/*
Function: updateDetails
Description: Allows the customer to update their email and phone number after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::updateDetails() void CustomerMenu::updateDetails()
{ {
std::string email, phone; std::string email, phone;
util::clear(); util::clear();
std::cout << "Update Details\n";
std::cout << "Enter new email: "; std::cout << "Enter new email: ";
util::read(email); util::read(email);
if (!util::isEmailValid(email)) if (!util::isEmailValid(email))
{ {
std::cout << "Error: Email is invalid!"; std::cout << "Error: Email is invalid!\n";
util::pressEnter(); util::pressEnter();
return; return;
} }
@@ -149,64 +157,35 @@ void CustomerMenu::updateDetails()
util::read(phone); util::read(phone);
if (!util::isPhoneNumberValid(phone)) if (!util::isPhoneNumberValid(phone))
{ {
std::cout << "Error: Phone number is invalid!"; std::cout << "Error: Phone number is invalid!\n";
util::pressEnter(); util::pressEnter();
return; return;
} }
m_controller.updateUserDetails(email, phone); m_controller.updateUserDetails(email, phone);
std::cout << "Profile details updated successfully"; std::cout << "Profile details updated successfully\n";
util::pressEnter(); util::pressEnter();
} }
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services) /*
{ Function: selectService
util::Map<int, const Service*> activeServicesMap; Description: Allows the customer to select a service, provide vehicle details,
int currentIndex = 1; and book the service through the controller.
int userInputIndex; Parameter: None
std::cout << std::left Return type: void
<< 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 = util::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];
}
void CustomerMenu::selectService() void CustomerMenu::selectService()
{ {
std::string vehicleNumber, vehicleBrand, vehicleModel; std::string vehicleNumber, vehicleBrand, vehicleModel;
auto services = m_controller.getServices();
util::Vector<std::string> selectedServices;
util::clear(); 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); const Service* selectedService = selectServiceFromServices(services);
if (selectedService == nullptr) if (selectedService == nullptr)
{ {
@@ -216,6 +195,7 @@ void CustomerMenu::selectService()
} }
selectedServices.push_back(selectedService->getId()); selectedServices.push_back(selectedService->getId());
util::clear(); util::clear();
std::cout << "Enter Vehicle Details\n";
std::cout << "Enter vehicle number: "; std::cout << "Enter vehicle number: ";
util::read(vehicleNumber); util::read(vehicleNumber);
std::cout << "Enter vehicle brand: "; std::cout << "Enter vehicle brand: ";
@@ -227,61 +207,37 @@ void CustomerMenu::selectService()
util::pressEnter(); util::pressEnter();
} }
static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages) /*
{ Function: selectComboPackage
util::Map<int, const ComboPackage*> activeComboPackages; Description: Allows the customer to select a combo package, provide vehicle details,
int currentIndex = 1; and book the package through the controller.
int userInputIndex; Parameter: None
std::cout << std::left Return type: void
<< 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) << util::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];
}
void CustomerMenu::selectComboPackage() void CustomerMenu::selectComboPackage()
{ {
std::string vehicleNumber, vehicleBrand, vehicleModel; std::string vehicleNumber, vehicleBrand, vehicleModel;
auto comboPackages = m_controller.getComboPackages();
util::clear(); util::clear();
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages); std::cout << "Select a Combo Package\n";
if (selectedComboPackage == nullptr) 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(); util::pressEnter();
return; 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(); util::clear();
std::cout << "Enter the vehicle details\n";
std::cout << "Enter vehicle number: "; std::cout << "Enter vehicle number: ";
util::read(vehicleNumber); util::read(vehicleNumber);
std::cout << "Enter vehicle brand: "; std::cout << "Enter vehicle brand: ";
@@ -289,10 +245,19 @@ void CustomerMenu::selectComboPackage()
std::cout << "Enter vehicle model: "; std::cout << "Enter vehicle model: ";
util::read(vehicleModel); util::read(vehicleModel);
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, 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(); 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() void CustomerMenu::viewServiceHistory()
{ {
util::clear(); util::clear();
@@ -300,16 +265,17 @@ void CustomerMenu::viewServiceHistory()
const User* currentUser = m_controller.getAuthenticatedUser(); const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId(); std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID); util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
std::cout << "View Service History" << std::endl;
if (serviceBookingsByCurrentUser.getSize() != 0) if (serviceBookingsByCurrentUser.getSize() != 0)
{ {
std::cout << std::left std::cout << std::left
<< std::setw(12) << "Booking ID" << std::setw(15) << "Booking ID"
<< std::setw(20) << "Technician" << std::setw(20) << "Technician"
<< std::setw(15) << "Vehicle Brand" << std::setw(20) << "Vehicle Brand"
<< std::setw(15) << "Vehicle Number" << std::setw(20) << "Vehicle Number"
<< std::setw(15) << "Vehicle Model" << std::setw(20) << "Vehicle Model"
<< std::setw(10) << "Discount %" << std::setw(20) << "Discount %"
<< std::setw(12) << "Status" << std::setw(20) << "Status"
<< std::endl; << std::endl;
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++) for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
{ {
@@ -318,13 +284,13 @@ void CustomerMenu::viewServiceHistory()
? "Not Assigned" ? "Not Assigned"
: currentBooking->getAssignedTechnician()->getName(); : currentBooking->getAssignedTechnician()->getName();
std::cout << std::left std::cout << std::left
<< std::setw(12) << currentBooking->getId() << std::setw(15) << currentBooking->getId()
<< std::setw(20) << technicianName << std::setw(20) << technicianName
<< std::setw(15) << currentBooking->getVehicleBrand() << std::setw(20) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleNumber() << std::setw(20) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleModel() << std::setw(20) << currentBooking->getVehicleModel()
<< std::setw(10) << currentBooking->getDiscountPercentage() << std::setw(20) << currentBooking->getDiscountPercentage()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) << std::setw(20) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::endl; << std::endl;
hasServiceHistory = true; hasServiceHistory = true;
} }
@@ -333,155 +299,73 @@ void CustomerMenu::viewServiceHistory()
{ {
std::cout << "No history available." << std::endl; std::cout << "No history available." << std::endl;
} }
util::pressEnter();
} }
static std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices) /*
{ Function: completePayments
int currentIndex = 1, choice; Description: Allows the customer to complete pending payments for invoices.
util::Map<int, const Invoice*> pendingInvoicesForPayment; Validates invoice selection and payment mode before completing payment.
std::cout << std::left Parameters:
<< std::setw(6) << "Index" - None
<< std::setw(12) << "BookingID" Returns:
<< std::setw(15) << "VehicleBrand" - void
<< std::setw(15) << "VehicleNumber" */
<< std::setw(12) << "TechID"
<< std::setw(20) << "TechnicianName"
<< std::setw(10) << "Discount(%)"
<< std::setw(12) << "TotalAmount"
<< std::setw(20) << "InvoiceDate"
<< std::endl;
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
{
const Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING)
{
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentInvoice->getBookingId()
<< std::setw(15) << currentInvoice->getBooking()->getVehicleBrand()
<< std::setw(15) << currentInvoice->getBooking()->getVehicleNumber()
<< std::setw(12) << currentInvoice->getBooking()->getAssignedTechnician()->getId()
<< std::setw(20) << currentInvoice->getBooking()->getAssignedTechnician()->getName()
<< std::setw(10) << currentInvoice->getDiscountPercentage()
<< std::setw(12) << currentInvoice->getTotalAmount()
<< std::setw(20) << currentInvoice->getInvoiceDate().toString()
<< std::endl;
pendingInvoicesForPayment.insert(currentIndex++, currentInvoice);
}
}
if (pendingInvoicesForPayment.getSize() == 0)
{
std::cout << "No pending invoices available for payment.\n";
return "";
}
std::cout << "Select the Invoice to pay (Index): ";
util::read(choice);
int selectedIndex = pendingInvoicesForPayment.find(choice);
if (selectedIndex != -1)
{
const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex);
return selectedInvoice->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
}
static util::PaymentMode selectPaymentMode()
{
int choice;
std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: ";
util::read(choice);
if (choice == 1)
{
std::cout << "Offline mode selected.\n";
return util::PaymentMode::OFFLINE;
}
else if (choice == 2)
{
std::cout << "Online mode selected.\n";
return util::PaymentMode::ONLINE;
}
else
{
std::cout << "Invalid choice, Offline mode selected.\n";
return util::PaymentMode::OFFLINE;
}
}
void CustomerMenu::completePayments() void CustomerMenu::completePayments()
{ {
util::clear(); util::clear();
std::cout << "Complete Payments\n";
util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser(); util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices); 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, util::PaymentStatus::PENDING);
if (selectedID == "") if (selectedID == "")
{ {
std::cout << "Payment failed.\n"; std::cout << "Payment failed.\n";
util::pressEnter();
return; return;
} }
util::PaymentMode paymentMode = selectPaymentMode(); util::PaymentMode paymentMode = selectPaymentMode();
m_controller.completePayment(selectedID, paymentMode); m_controller.completePayment(selectedID, paymentMode);
std::cout << "Payment completed successfully.\n"; std::cout << "Payment completed successfully.\n";
}
static void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
{
if (currentUserInvoices.getSize() == 0)
{
std::cout << "No invoices found for this account." << std::endl;
util::pressEnter(); util::pressEnter();
return;
}
else
{
for (int index = 0; index < currentUserInvoices.getSize(); index++)
{
const Invoice* currentInvoice = currentUserInvoices.getValueAt(index);
if (currentInvoice)
{
std::cout << "\nInvoice Details\n";
std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl;
std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl;
std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl;
std::cout << "Technician ID: " << currentInvoice->getBooking()->getAssignedTechnician()->getId() << std::endl;
std::cout << "Technician Name: " << currentInvoice->getBooking()->getAssignedTechnician()->getName() << std::endl;
std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl;
std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl;
std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl;
std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl;
auto inventoryItemsInInvoice = currentInvoice->getParts();
std::cout << "\nItems Used:\n";
std::cout << std::left
<< std::setw(20) << "ItemName"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
std::cout << std::string(40, '-') << std::endl;
for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++)
{
InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator);
std::cout << std::left
<< std::setw(20) << currentItem->getPartName()
<< std::setw(10) << currentItem->getQuantity()
<< std::setw(10) << currentItem->getPrice()
<< std::endl;
}
}
else
{
throw std::runtime_error("Null invoice encountered while displaying invoices.");
}
}
}
} }
/*
Function: viewInvoices
Description: Displays invoices associated with the customer by calling displayInvoices.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewInvoices() void CustomerMenu::viewInvoices()
{ {
util::clear(); util::clear();
std::cout << "View Invoices\n";
util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser(); util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser();
displayInvoices(currentUserInvoices); displayInvoices(currentUserInvoices);
util::pressEnter();
} }
/* /*
@@ -497,38 +381,6 @@ void CustomerMenu::viewNotifications()
viewAndDeleteNotification(m_controller); viewAndDeleteNotification(m_controller);
} }
/*
Function: getNotificationPreference (static helper)
Description: Helper function to configure notification preferences for a specific service.
Parameters:
- serviceName: Name of the service for which notifications are being configured.
Returns:
- bool: True if notifications are enabled, False if disabled.
*/
static bool getNotificationPreference(const std::string& serviceName)
{
int choice;
while (true)
{
util::clear();
std::cout << " Configure Notification Preferences\n";
std::cout << "\n" << serviceName << " Notifications\n";
std::cout << "1. Enable Notifications\n";
std::cout << "2. Disable Notifications\n";
std::cout << "Enter your choice: ";
util::read(choice);
if (choice == 1)
{
return true;
}
if (choice == 2)
{
return false;
}
std::cout << "\nInvalid choice. Please enter 1 or 2.\n";
util::pressEnter();
}
}
/* /*
Function: configureNotifications Function: configureNotifications
@@ -1,10 +1,11 @@
/* /*
File: CustomerMenu.h File: CustomerMenu.h
Description: Declares the CustomerMenu class which provides the customer-facing console menu in the Vehicle Service Management System. Description: Header file declaring the CustomerMenu class, which provides
Supports operations such as account management, service selection, combo package booking, viewing service history, customer operations such as selecting services, booking combo
handling payments and invoices, and managing notifications. packages, updating profile details, managing payments, viewing
invoices, and configuring notifications.
Author: Trenser Author: Trenser
Date: 19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,6 @@ Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <iomanip>
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "JobCard.h" #include "JobCard.h"
@@ -35,10 +34,11 @@ void TechnicianMenu::showMenu()
int choice; int choice;
util::clear(); util::clear();
std::cout << "Technician Menu" std::cout << "Technician Menu"
<< "\n1. Mark Job as Completed" << "\n1. Display My Jobs"
<< "\n2. View Notifications" << "\n2. Update Job Status"
<< "\n3. Change Password" << "\n3. View Notifications"
<< "\n4. Logout" << "\n4. Change Password"
<< "\n5. Logout"
<< "\nEnter a choice: "; << "\nEnter a choice: ";
util::read(choice); util::read(choice);
if (!handleOperation(choice)) if (!handleOperation(choice))
@@ -65,15 +65,18 @@ bool TechnicianMenu::handleOperation(int choice)
switch (choice) switch (choice)
{ {
case 1: case 1:
completeJob(); displayJobs();
break; break;
case 2: case 2:
viewNotifications(); updateJobStatus();
break; break;
case 3: case 3:
changePassword(); viewNotifications();
break; break;
case 4: case 4:
changePassword();
break;
case 5:
logout(); logout();
return false; return false;
default: default:
@@ -83,69 +86,65 @@ bool TechnicianMenu::handleOperation(int choice)
return true; return true;
} }
static std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards, util::Map<int, const JobCard*>& incompleteJobCards) /*
Function: displayJobs
Description: Displays all Jobs assigned to a Technician
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::displayJobs()
{ {
int currentIndex = 1; util::clear();
int choice; std::cout << "My Jobs\n";
bool hasIncompleteJobCard = false; util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
std::cout << std::left util::Map<std::string, const JobCard*> jobCards = filterStartedJobCards(assignedJobCards);
<< std::setw(6) << "Index" displayAllJobs(jobCards);
<< std::setw(12) << "BookingID" util::pressEnter();
<< std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID"
<< std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
{
std::cout << std::left << std::setw(6) << currentIndex
<< std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName()
<< std::setw(12) << currentJobCard->getServiceId()
<< std::endl;
hasIncompleteJobCard = true;
incompleteJobCards.insert(currentIndex++, currentJobCard);
}
}
if (!hasIncompleteJobCard)
{
std::cout << "No pending jobs are present.\n";
return "";
}
std::cout << "Select the Job Card to complete (Index): ";
util::read(choice);
int selectedJobCardIndex = incompleteJobCards.find(choice);
if (selectedJobCardIndex != -1)
{
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
return selectedJobCard->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
} }
/*
void TechnicianMenu::completeJob() 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(); util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<int, const JobCard*> incompleteJobCards; std::cout << "Select the type of job you want to update\n1.Started\n2.Inprogress\nChoice: ";
std::cout << "Jobs to be completed.\n"; util::read(choice);
std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards); if (choice == 1)
if (selectedJobID == "")
{ {
std::cout << "Failed to complete the job.\n"; selectedJobStatus = util::ServiceJobStatus::STARTED;
}
else if (choice == 2)
{
selectedJobStatus = util::ServiceJobStatus::IN_PROGRESS;
} }
else else
{ {
m_controller.completeJob(selectedJobID); std::cout << "Invalid choice. Please try again.\n";
std::cout << "Job marked as completed.\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();
} }
/* /*
@@ -178,23 +177,8 @@ Description: Allows the technician to change their password after validation.
Parameter: None Parameter: None
Return type: void Return type: void
*/ */
void TechnicianMenu::changePassword() void TechnicianMenu::changePassword()
{ {
std::string newPassword; changePasswordHelper(m_controller);
while (true)
{
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!\n";
util::pressEnter();
continue;
}
m_controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
} }
@@ -6,6 +6,7 @@ Description: Header file declaring the TechnicianMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -16,7 +17,8 @@ private:
bool handleOperation(int choice); bool handleOperation(int choice);
public: public:
void showMenu(); void showMenu();
void completeJob(); void displayJobs();
void updateJobStatus();
void viewNotifications(); void viewNotifications();
void logout(); void logout();
void changePassword(); void changePassword();
@@ -6,11 +6,14 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "UserInterface.h"
#include <iostream>
#include <stdexcept>
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h" #include "User.h"
#include "UserInterface.h"
#include "Validator.h" #include "Validator.h"
/* /*
@@ -22,6 +25,8 @@ Return type: void
*/ */
void UserInterface::run() void UserInterface::run()
{ {
try
{
m_controller.loadSystemData(); m_controller.loadSystemData();
m_controller.runSystemChecks(); m_controller.runSystemChecks();
bool isMenuActive = true; bool isMenuActive = true;
@@ -45,6 +50,19 @@ void UserInterface::run()
} }
} }
m_controller.saveSystemData(); 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;
}
} }
/* /*
@@ -84,6 +102,7 @@ void UserInterface::login()
{ {
std::string username, password; std::string username, password;
util::clear(); util::clear();
std::cout << "Login\n";
std::cout << "Enter username: "; std::cout << "Enter username: ";
util::read(username); util::read(username);
std::cout << "Enter password: "; std::cout << "Enter password: ";
@@ -91,7 +110,7 @@ void UserInterface::login()
if (m_controller.login(username, password)) if (m_controller.login(username, password))
{ {
const User* authenticatedUser = m_controller.getAuthenticatedUser(); const User* authenticatedUser = m_controller.getAuthenticatedUser();
if (authenticatedUser != nullptr) if (authenticatedUser && authenticatedUser->getState() != util::State::INACTIVE)
{ {
switch (authenticatedUser->getUserType()) switch (authenticatedUser->getUserType())
{ {
@@ -109,25 +128,32 @@ void UserInterface::login()
break; break;
} }
} }
else if (authenticatedUser && authenticatedUser->getState() == util::State::INACTIVE)
{
std::cout << "\nError: Your account has been disabled. Please contact your Administrator.";
util::pressEnter();
}
} }
else else
{ {
std::cout << "\nError: Invalid Username or Password"; std::cout << "\nError: Invalid Username or Password";
util::pressEnter();
} }
} }
/* /*
Function: registerCustomer Function: registerCustomer
Description: Handles the registration process for new customers. Description: Registers a new customer by collecting and validating details such as
Parameters: username, name, email, password, and phone number. Delegates creation
- None to the controller.
Returns: Parameter: None
- void Return type: void
*/ */
void UserInterface::registerCustomer() void UserInterface::registerCustomer()
{ {
std::string username, name, email, phone, password; std::string username, name, email, phone, password;
util::clear(); util::clear();
std::cout << "Register Customer\n";
std::cout << "Enter username: "; std::cout << "Enter username: ";
util::read(username); util::read(username);
std::cout << "Enter name: "; std::cout << "Enter name: ";
@@ -7,6 +7,7 @@ Description: Header file declaring the UserInterface class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
#include "AdminMenu.h" #include "AdminMenu.h"