Compare commits

..

7 Commits

Author SHA1 Message Date
Jissin Mathew ce50467816 Fix Technician Job Status Update Screen UI and Formatting Issues
- Corrected inconsistent status label formatting: replaced "Inprogress" with "In Progress" in TechnicianMenu and MenuHelper.
- Updated headings in selectJobCardToUpdate to clearer phrasing:
  - "Select a job to mark as In Progress"
  - "Select a job to mark as Completed".
- Added spacing before and after the "No jobs available" message to improve readability and provide clear separation from headings.
- Replaced duplicated prompt "Select the Job Card to Update (Index):" with concise "Enter the job index to update:".
- Improved TechnicianMenu option display to show "In Progress" instead of "Inprogress".

Fixes #1808
2026-06-01 18:02:45 +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
12 changed files with 150 additions and 77 deletions
@@ -392,9 +392,9 @@ Parameters:
Returns: Returns:
- void - void
*/ */
void Controller::completeJob(const std::string& jobID) void Controller::updateJobStatus(const std::string& jobID)
{ {
m_serviceManagementService.completeJob(jobID); m_serviceManagementService.updateJobStatus(jobID);
} }
/* /*
@@ -472,7 +472,7 @@ Returns:
*/ */
util::Map<std::string, const Invoice*> Controller::getAllInvoices() util::Map<std::string, const Invoice*> Controller::getAllInvoices()
{ {
auto invoices = m_paymentManagementService.getAllInvoice(); auto invoices = m_paymentManagementService.getAllInvoices();
util::Map<std::string, const Invoice*> readOnlyInvoice; util::Map<std::string, const Invoice*> readOnlyInvoice;
for (int iterator = 0; iterator < invoices.getSize(); iterator++) for (int iterator = 0; iterator < invoices.getSize(); iterator++)
{ {
@@ -489,7 +489,7 @@ Parameters:
Returns: Returns:
- void - void
*/ */
void Controller::confirmPayment(std::string invoiceID) void Controller::confirmPayment(const std::string& invoiceID)
{ {
m_paymentManagementService.confirmPayment(invoiceID); m_paymentManagementService.confirmPayment(invoiceID);
} }
@@ -59,13 +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(); util::Map<std::string, const Invoice*> getAllInvoices();
void confirmPayment(std::string invoiceID); 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);
@@ -394,7 +394,7 @@ Parameters:
Returns: Returns:
- util::Map<std::string, Invoice*>&: Map of invoice IDs to invoice objects - util::Map<std::string, Invoice*>&: Map of invoice IDs to invoice objects
*/ */
util::Map<std::string, Invoice*>& PaymentManagementService::getAllInvoice() util::Map<std::string, Invoice*>& PaymentManagementService::getAllInvoices()
{ {
return m_dataStore.getInvoices(); return m_dataStore.getInvoices();
} }
@@ -410,26 +410,22 @@ Returns:
Throws: Throws:
- std::runtime_error if the invoice ID is invalid - std::runtime_error if the invoice ID is invalid
*/ */
void PaymentManagementService::confirmPayment(std::string invoiceID) void PaymentManagementService::confirmPayment(const std::string& invoiceID)
{ {
std::string title, message;
auto& currentInvoices = m_dataStore.getInvoices(); auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID); int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex != -1) if (invoiceIndex == -1)
{ {
throw std::runtime_error("Payment confirmation failed: invalid invoice ID.");
}
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
if (invoice && invoice->getStatus() != util::PaymentStatus::COMPLETED) if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID)
{ {
throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation.");
}
User* currentUser = invoice->getBooking()->getCustomer(); User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::COMPLETED); invoice->setStatus(util::PaymentStatus::COMPLETED);
title = "Payment Confirmed"; std::string title = "Payment Confirmed";
message = "Payment Confirmed for Invoice ID " + invoiceID; std::string message = "Payment Confirmed for Invoice ID " + invoiceID;
sendNotification(currentUser, title, message); sendNotification(currentUser, title, message);
} }
}
else
{
throw std::runtime_error("Payment failed: invalid invoice ID.");
}
}
@@ -28,8 +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*>& getAllInvoice(); util::Map<std::string, Invoice*>& getAllInvoices();
void confirmPayment(std::string invoiceID); 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;
@@ -1080,7 +1080,7 @@ static bool hasCompletedAllJobs(std::string bookingId, util::Map<std::string, Jo
JobCard* currentJob = currentAssignedJobs.getValueAt(iterator); JobCard* currentJob = currentAssignedJobs.getValueAt(iterator);
if (currentJob->getBookingId() == bookingId) if (currentJob->getBookingId() == bookingId)
{ {
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) if (currentJob->getStatus() != util::ServiceJobStatus::COMPLETED && currentJob->getStatus() != util::ServiceJobStatus::CANCELLED)
{ {
return false; return false;
} }
@@ -1090,18 +1090,19 @@ static bool hasCompletedAllJobs(std::string bookingId, util::Map<std::string, Jo
} }
/* /*
Function: completeJob Function: updateJobStatus
Description: Marks a job card as completed for the authenticated technician. Description:
If all job cards in the booking are completed, marks the booking as completed Updates the status of a job card assigned to the currently authenticated technician.
and generates an invoice. - If the job is STARTED, it moves to IN_PROGRESS.
- If the job is IN_PROGRESS, it moves to COMPLETED.
When all jobs in a service booking are completed, the booking status is updated,
an invoice is generated, and a notification is sent to the customer.
Parameters: Parameters:
- jobID: std::string, ID of the job card - jobID: const std::string&, unique identifier of the job card to update.
Returns: Returns:
- void - void
Throws:
- std::runtime_error if technician is not authenticated, job card not found, or job already completed
*/ */
void ServiceManagementService::completeJob(const std::string& jobID) void ServiceManagementService::updateJobStatus(const std::string& jobID)
{ {
AuthenticationManagementService authenticationManagementService; AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
@@ -1126,19 +1127,13 @@ void ServiceManagementService::completeJob(const std::string& jobID)
} }
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{ {
currentJob->setStatus(util::ServiceJobStatus::COMPLETED); currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
jobStatusUpdated = true; jobStatusUpdated = true;
} }
} else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
else
{ {
throw std::runtime_error("Failed to complete the job, some error occurred or job already completed."); currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
} jobStatusUpdated = true;
if (!jobStatusUpdated)
{
throw std::runtime_error("Failed to complete the job, some error occurred or job already completed.");
}
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted) if (serviceBookingCompleted)
{ {
@@ -1149,3 +1144,13 @@ void ServiceManagementService::completeJob(const std::string& jobID)
sendNotification(currentJob->getBooking()->getCustomer(), title, message); sendNotification(currentJob->getBooking()->getCustomer(), title, message);
} }
} }
}
else
{
throw std::runtime_error("Failed to update job status. Job may already be completed.");
}
if (!jobStatusUpdated)
{
throw std::runtime_error("Failed to update job status. Job may already be completed.");
}
}
@@ -37,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);
@@ -38,6 +38,7 @@ namespace util
PENDING, PENDING,
STARTED, STARTED,
COMPLETED, COMPLETED,
IN_PROGRESS,
CANCELLED CANCELLED
}; };
@@ -212,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");
} }
@@ -244,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");
} }
@@ -503,7 +503,7 @@ void AdminMenu::displayUsers()
/* /*
Function: confirmPayment Function: confirmPayment
Description: Confirms payment for a selected invoice. Validates invoice status, updates payment date, Description: Confirms payment for a selected invoice. Validates invoice status, updates payment date,
sets status to PAID, and sends a notification to the customer. sets status to COMPLETED, and sends a notification to the customer.
Parameters: Parameters:
- invoiceID: std::string, ID of the invoice to confirm - invoiceID: std::string, ID of the invoice to confirm
Returns: Returns:
@@ -520,19 +520,19 @@ void AdminMenu::confirmPayment()
util::pressEnter(); util::pressEnter();
return; return;
} }
bool hasPaidInvoice = false; bool hasConfirmableInvoice = false;
for (int index = 0; index < invoiceList.getSize(); ++index) for (int index = 0; index < invoiceList.getSize(); ++index)
{ {
const Invoice* invoice = invoiceList.getValueAt(index); const Invoice* invoice = invoiceList.getValueAt(index);
if (invoice && invoice->getStatus() == util::PaymentStatus::PAID) if (invoice && invoice->getStatus() == util::PaymentStatus::PAID)
{ {
hasPaidInvoice = true; hasConfirmableInvoice = true;
break; break;
} }
} }
if (!hasPaidInvoice) if (!hasConfirmableInvoice)
{ {
std::cout << "No pending invoices available for payment.\n"; std::cout << "No invoices awaiting confirmation.\n";
util::pressEnter(); util::pressEnter();
return; return;
} }
@@ -631,7 +631,6 @@ inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserIn
std::cout << "Unable to fetch the selected invoice\n"; std::cout << "Unable to fetch the selected invoice\n";
doRun = false; doRun = false;
} }
} while (doRun); } while (doRun);
} }
} }
@@ -650,7 +649,35 @@ inline util::Map<std::string, const JobCard*> filterStartedJobCards(util::Map<st
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{ {
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && currentJobCard->getStatus() == util::ServiceJobStatus::STARTED) if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS))
{
startedJobCards.insert(currentJobCard->getId(), currentJobCard);
}
}
return startedJobCards;
}
/*
Function: filterJobCards
Description:
Filters the given list of job cards and returns only those
whose status matches the specified ServiceJobStatus.
Parameters:
- assignedJobCards: util::Map<std::string, const JobCard*>&
Map of job card IDs to JobCard pointers assigned to the technician.
- selectedJobStatus: util::ServiceJobStatus
The status type to filter job cards by.
Returns:
- util::Map<std::string, const JobCard*>
A map containing only job cards with the specified status.
*/
inline util::Map<std::string, const JobCard*> filterJobCards(util::Map<std::string, const JobCard*>& assignedJobCards, util::ServiceJobStatus selectedJobStatus)
{
util::Map<std::string, const JobCard*> startedJobCards;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && currentJobCard->getStatus() == selectedJobStatus)
{ {
startedJobCards.insert(currentJobCard->getId(), currentJobCard); startedJobCards.insert(currentJobCard->getId(), currentJobCard);
} }
@@ -679,16 +706,18 @@ inline void displayAllJobs(util::Map<std::string, const JobCard*>& assignedJobCa
<< std::setw(12) << "JobID" << std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName" << std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID" << std::setw(12) << "ServiceID"
<< std::setw(12) << "Status"
<< std::endl; << std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{ {
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS))
{ {
std::cout << std::left << std::setw(12) << currentJobCard->getBookingId() std::cout << std::left << std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId() << std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName() << std::setw(20) << util::truncateString(currentJobCard->getService()->getName(), 15)
<< std::setw(12) << currentJobCard->getServiceId() << std::setw(12) << currentJobCard->getServiceId()
<< std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus())
<< std::endl; << std::endl;
} }
} }
@@ -702,16 +731,31 @@ Parameters:
Returns: Returns:
- std::string: ID of the selected job card, or empty string if none selected - std::string: ID of the selected job card, or empty string if none selected
*/ */
inline std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards) inline std::string selectJobCardToUpdate(util::Map<std::string, const JobCard*>& assignedJobCards, util::ServiceJobStatus selectedJobStatusType)
{ {
util::Map<int, const JobCard* > incompleteJobCards; util::Map<int, const JobCard* > incompleteJobCards;
if (assignedJobCards.getSize() == 0) if (assignedJobCards.getSize() == 0)
{ {
std::cout << "No started jobs available to complete.\n"; std::cout << "\nNo jobs available.\n\n";
return ""; return "";
} }
int currentIndex = 1; int currentIndex = 1;
int choice; int choice;
if (selectedJobStatusType == util::ServiceJobStatus::STARTED)
{
util::clear();
std::cout << "Select a job to mark as In Progress\n";
}
else if (selectedJobStatusType == util::ServiceJobStatus::IN_PROGRESS)
{
util::clear();
std::cout << "Select a job to mark as Completed\n";
}
else
{
std::cout << "Unable to update completed or pending jobs.\n\n";
return "";
}
std::cout << std::endl; std::cout << std::endl;
std::cout << std::left std::cout << std::left
<< std::setw(6) << "Index" << std::setw(6) << "Index"
@@ -719,22 +763,24 @@ inline std::string selectJobCardToComplete(util::Map<std::string, const JobCard*
<< std::setw(12) << "JobID" << std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName" << std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID" << std::setw(12) << "ServiceID"
<< std::setw(12) << "JobStatus"
<< std::endl; << std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{ {
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) if (currentJobCard && (currentJobCard->getStatus() == selectedJobStatusType))
{ {
std::cout << std::left << std::setw(6) << currentIndex std::cout << std::left << std::setw(6) << currentIndex
<< std::setw(12) << currentJobCard->getBookingId() << std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId() << std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName() << std::setw(20) << util::truncateString(currentJobCard->getService()->getName(), 15)
<< std::setw(12) << currentJobCard->getServiceId() << std::setw(12) << currentJobCard->getServiceId()
<< std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus())
<< std::endl; << std::endl;
incompleteJobCards.insert(currentIndex++, currentJobCard); incompleteJobCards.insert(currentIndex++, currentJobCard);
} }
} }
std::cout << "Select the Job Card to complete (Index): "; std::cout << "Enter the job index to update: ";
util::read(choice); util::read(choice);
int selectedJobCardIndex = incompleteJobCards.find(choice); int selectedJobCardIndex = incompleteJobCards.find(choice);
if (selectedJobCardIndex != -1) if (selectedJobCardIndex != -1)
@@ -745,7 +791,7 @@ inline std::string selectJobCardToComplete(util::Map<std::string, const JobCard*
else else
{ {
std::cout << "Invalid index.\n"; std::cout << "Invalid index.\n";
std::cout << "Failed to complete jobs.\n\n"; std::cout << "Failed to update job.\n\n";
return ""; return "";
} }
} }
@@ -35,7 +35,7 @@ void TechnicianMenu::showMenu()
util::clear(); util::clear();
std::cout << "Technician Menu" std::cout << "Technician Menu"
<< "\n1. Display My Jobs" << "\n1. Display My Jobs"
<< "\n2. Mark Job as Completed" << "\n2. Update Job Status"
<< "\n3. View Notifications" << "\n3. View Notifications"
<< "\n4. Change Password" << "\n4. Change Password"
<< "\n5. Logout" << "\n5. Logout"
@@ -68,7 +68,7 @@ bool TechnicianMenu::handleOperation(int choice)
displayJobs(); displayJobs();
break; break;
case 2: case 2:
completeJob(); updateJobStatus();
break; break;
case 3: case 3:
viewNotifications(); viewNotifications();
@@ -99,31 +99,50 @@ void TechnicianMenu::displayJobs()
util::clear(); util::clear();
std::cout << "My Jobs\n"; std::cout << "My Jobs\n";
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser(); util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<std::string, const JobCard*> startedJobCards = filterStartedJobCards(assignedJobCards); util::Map<std::string, const JobCard*> jobCards = filterStartedJobCards(assignedJobCards);
displayAllJobs(startedJobCards); displayAllJobs(jobCards);
util::pressEnter(); util::pressEnter();
} }
/* /*
Function: completeJob Function: updateJobStatus
Description: Allows the technician to mark a selected job card as completed. Description: Allows the technician to update a selected job card.
Validates selection and updates job status through the controller. Validates selection and updates job status through the controller.
Parameters: Parameters:
- None - None
Returns: Returns:
- void - void
*/ */
void TechnicianMenu::completeJob() void TechnicianMenu::updateJobStatus()
{ {
util::clear(); util::clear();
std::cout << "Complete Job\n"; 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<std::string, const JobCard*> startedJobCards = filterStartedJobCards(assignedJobCards); std::cout << "Select the type of job you want to update:\n1.Started\n2.In Progress\nChoice: ";
std::string selectedJobID = selectJobCardToComplete(startedJobCards); util::read(choice);
if (choice == 1)
{
selectedJobStatus = util::ServiceJobStatus::STARTED;
}
else if (choice == 2)
{
selectedJobStatus = util::ServiceJobStatus::IN_PROGRESS;
}
else
{
std::cout << "Invalid choice. Please try again.\n";
util::pressEnter();
return;
}
util::Map<std::string, const JobCard*> selectedTypeJobCard = filterJobCards(assignedJobCards, selectedJobStatus);
selectedJobID = selectJobCardToUpdate(selectedTypeJobCard, selectedJobStatus);
if (!selectedJobID.empty()) if (!selectedJobID.empty())
{ {
m_controller.completeJob(selectedJobID); m_controller.updateJobStatus(selectedJobID);
std::cout << "\nJob marked as completed.\n\n"; std::cout << "\nJob status updated.\n\n";
} }
util::pressEnter(); util::pressEnter();
} }
@@ -18,7 +18,7 @@ private:
public: public:
void showMenu(); void showMenu();
void displayJobs(); void displayJobs();
void completeJob(); void updateJobStatus();
void viewNotifications(); void viewNotifications();
void logout(); void logout();
void changePassword(); void changePassword();