Fix Completing a Job Throws an Exception

Changes:

- Refactored ServiceManagementService::updateJobStatus() to use tracked
  job card references instead of raw pointers, ensuring consistent state
  updates.
- Added proper null checks and error handling for current job retrieval
  to prevent unexpected termination.
- Updated logic to mark tracked job records as MODIFIED when status
  transitions occur (STARTED → IN_PROGRESS, IN_PROGRESS → COMPLETED).
- Simplified control flow and indentation for better readability and
  maintainability.

Fixes #2076
This commit is contained in:
Jissin Mathew
2026-06-17 17:01:34 +05:30
parent 4243f4e43f
commit bb0d186b62
2 changed files with 42 additions and 37 deletions
@@ -220,6 +220,11 @@ void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cac
if (oldIndex != -1)
{
TrackedRecord<TObject>& oldRecord = oldCache.getValueAt(oldIndex);
if (oldRecord.state == RecordState::MODIFIED)
{
cache.insert(id, oldRecord);
continue;
}
*oldRecord.data = *refreshedRecord.data;
oldRecord.slotIndex = refreshedRecord.slotIndex;
oldRecord.state = refreshedRecord.state;
@@ -880,44 +880,44 @@ Returns:
void ServiceManagementService::updateJobStatus(const std::string& jobID)
{
DataStoreLockGuard lock(m_dataStore);
AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted;
JobCard* currentJob;
User* currentTechnician = authenticationManagementService.getAuthenticatedUser();
if (currentTechnician == nullptr)
{
throw std::runtime_error("Unable to fetch current technician.");
}
util::Map<std::string, JobCard*> currentAssignedJobs = getJobCards(currentTechnician->getId());
if (currentAssignedJobs.getSize() == 0)
{
throw std::runtime_error("No job cards assigned to the technician.");
}
AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted;
User* currentTechnician = authenticationManagementService.getAuthenticatedUser();
if (currentTechnician == nullptr)
{
throw std::runtime_error("Unable to fetch current technician.");
}
util::Map<std::string, JobCard*> currentAssignedJobs = getJobCards(currentTechnician->getId());
if (currentAssignedJobs.getSize() == 0)
{
throw std::runtime_error("No job cards assigned to the technician.");
}
auto& trackedJobCards = m_dataStore.getJobCards();
auto& trackedServiceBookings = m_dataStore.getServiceBookings();
if (currentAssignedJobs.find(jobID) != -1)
{
if (currentAssignedJobs.find(jobID) != -1)
{
int jobIndex = trackedJobCards.find(jobID);
if (jobIndex == -1)
{
throw std::runtime_error("Unable to fetch current job.");
}
currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
if (currentJob == nullptr)
{
throw std::runtime_error("Unable to fetch current job.");
}
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
jobStatusUpdated = true;
}
auto& trackedCurrentJob = trackedJobCards.getValueAt(jobIndex);
JobCard* currentJob = trackedCurrentJob.data;
if (currentJob == nullptr)
{
throw std::runtime_error("Unable to fetch current job.");
}
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
trackedCurrentJob.state = RecordState::MODIFIED;
jobStatusUpdated = true;
}
else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
{
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
trackedCurrentJob.state = RecordState::MODIFIED;
jobStatusUpdated = true;
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted)
@@ -931,15 +931,15 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
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.");
}
}
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.");
}
m_dataStore.saveJobCards();
m_dataStore.saveServiceBookings();
}