Implement View Customer Notifications
<UserStory> NOT001: View Customer Notifications </UserStory> <Changes> 1. Added shared notification helper functions to display notifications in tabular format, support notification selection, and show full notification details. 2. Implemented notification deletion logic in Controller and UserManagementService to remove notifications for the authenticated user after viewing. 3. Updated CustomerMenu::viewNotifications() to use the shared notification viewing and deletion flow. </Changes> <Test> Precondition: 1. Customer is registered in the system. 2. Customer is logged into the system. 3. Customer has one or more notifications available. Steps: 1. Navigate to “View Notifications” from the customer menu. - Verify that the system displays the list of notifications with title and timestamp. 2. Select a notification from the displayed list. - Verify that the system displays the full notification details including message. 3. View the selected notification and continue. - Verify that the viewed notification is deleted from the system. 4. Navigate to “View Notifications” again. - Verify that the previously viewed notification no longer appears in the notification list. </Test> <Review> Sreeja Reghukumar, please review </Review>
This commit is contained in:
+1
@@ -180,6 +180,7 @@
|
|||||||
<ClInclude Include="utilities\Vector.h" />
|
<ClInclude Include="utilities\Vector.h" />
|
||||||
<ClInclude Include="views\AdminMenu.h" />
|
<ClInclude Include="views\AdminMenu.h" />
|
||||||
<ClInclude Include="views\CustomerMenu.h" />
|
<ClInclude Include="views\CustomerMenu.h" />
|
||||||
|
<ClInclude Include="views\MenuHelper.h" />
|
||||||
<ClInclude Include="views\TechnicianMenu.h" />
|
<ClInclude Include="views\TechnicianMenu.h" />
|
||||||
<ClInclude Include="views\UserInterface.h" />
|
<ClInclude Include="views\UserInterface.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
+3
@@ -233,5 +233,8 @@
|
|||||||
<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>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
+21
-1
@@ -1,4 +1,6 @@
|
|||||||
|
#include <stdexcept>
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
|
#include "User.h"
|
||||||
|
|
||||||
bool Controller::login(const std::string& username, const std::string& password)
|
bool Controller::login(const std::string& username, const std::string& password)
|
||||||
{
|
{
|
||||||
@@ -130,11 +132,29 @@ void Controller::completePayment(const std::string& invoiceID, util::PaymentMode
|
|||||||
|
|
||||||
util::Vector<const Notification*> Controller::getNotifications()
|
util::Vector<const Notification*> Controller::getNotifications()
|
||||||
{
|
{
|
||||||
return util::Vector<const Notification*>();
|
const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
|
||||||
|
if (!authenticatedUser)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No user is currently logged in!");
|
||||||
|
}
|
||||||
|
auto notifications = m_userManagementService.getUserNotifications(authenticatedUser->getId());
|
||||||
|
int numberOfNotifications = notifications.getSize();
|
||||||
|
util::Vector<const Notification*> readOnlyNotifications;
|
||||||
|
for (int index = 0; index < numberOfNotifications; index++)
|
||||||
|
{
|
||||||
|
readOnlyNotifications.push_back(notifications[index]);
|
||||||
|
}
|
||||||
|
return readOnlyNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::deleteNotification(const std::string& notificationID)
|
void Controller::deleteNotification(const std::string& notificationID)
|
||||||
{
|
{
|
||||||
|
const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
|
||||||
|
if (!authenticatedUser)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No user is currently logged in!");
|
||||||
|
}
|
||||||
|
m_userManagementService.deleteNotification(notificationID, authenticatedUser->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications)
|
void Controller::configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
|
#include "AuthenticationManagementService.h"
|
||||||
|
#include "UserManagementService.h"
|
||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
class ComboPackage;
|
class ComboPackage;
|
||||||
@@ -14,6 +16,9 @@ class Notification;
|
|||||||
|
|
||||||
class Controller
|
class Controller
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
AuthenticationManagementService m_authenticationManagementService;
|
||||||
|
UserManagementService m_userManagementService;
|
||||||
public:
|
public:
|
||||||
bool login(const std::string& username, const std::string& password);
|
bool login(const std::string& username, const std::string& password);
|
||||||
void logout();
|
void logout();
|
||||||
|
|||||||
+44
@@ -1 +1,45 @@
|
|||||||
|
#include <stdexcept>
|
||||||
#include "UserManagementService.h"
|
#include "UserManagementService.h"
|
||||||
|
#include "User.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID)
|
||||||
|
{
|
||||||
|
auto& usersMap = m_dataStore.getUsers();
|
||||||
|
if (usersMap.find(userID) == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No user found with given UserID");
|
||||||
|
}
|
||||||
|
User* user = usersMap[userID];
|
||||||
|
if (user)
|
||||||
|
{
|
||||||
|
auto& notifications = user->getNotifications();
|
||||||
|
int numberOfNotifications = notifications.getSize();
|
||||||
|
util::Vector<Notification*> notificationsVector;
|
||||||
|
for (int index = 0; index < numberOfNotifications; index++)
|
||||||
|
{
|
||||||
|
notificationsVector.push_back(notifications.getValueAt(index));
|
||||||
|
}
|
||||||
|
return notificationsVector;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid User object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
|
||||||
|
{
|
||||||
|
auto& usersMap = m_dataStore.getUsers();
|
||||||
|
if (usersMap.find(userID) == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No user found with given UserID");
|
||||||
|
}
|
||||||
|
User* user = usersMap[userID];
|
||||||
|
auto& notifications = user->getNotifications();
|
||||||
|
if (notifications.find(notificationID) == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No notification found with given NotificationID");
|
||||||
|
}
|
||||||
|
notifications.remove(notificationID);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CustomerMenu.h"
|
#include "CustomerMenu.h"
|
||||||
#include "InputHelper.h"
|
#include "InputHelper.h"
|
||||||
#include "OutputHelper.h"
|
#include "OutputHelper.h"
|
||||||
|
#include "MenuHelper.h"
|
||||||
|
|
||||||
void CustomerMenu::showMenu()
|
void CustomerMenu::showMenu()
|
||||||
{
|
{
|
||||||
@@ -65,6 +66,7 @@ void CustomerMenu::viewInvoices()
|
|||||||
|
|
||||||
void CustomerMenu::viewNotifications()
|
void CustomerMenu::viewNotifications()
|
||||||
{
|
{
|
||||||
|
viewAndDeleteNotification(m_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomerMenu::configureNotifications()
|
void CustomerMenu::configureNotifications()
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <iomanip>
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Controller.h"
|
||||||
|
#include "Notification.h"
|
||||||
|
#include "InputHelper.h"
|
||||||
|
#include "OutputHelper.h"
|
||||||
|
|
||||||
|
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
|
||||||
|
{
|
||||||
|
if (notifications.getSize() == 0)
|
||||||
|
{
|
||||||
|
std::cout << "No notifications available." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
util::Map<int, const Notification*> indexedNotifications;
|
||||||
|
std::cout << std::left
|
||||||
|
<< std::setw(6) << "Index"
|
||||||
|
<< std::setw(15) << "ID"
|
||||||
|
<< std::setw(30) << "Title"
|
||||||
|
<< std::setw(25) << "Timestamp"
|
||||||
|
<< std::endl;
|
||||||
|
int currentIndex = 1;
|
||||||
|
for (int index = 0; index < notifications.getSize(); index++)
|
||||||
|
{
|
||||||
|
const Notification* currentNotification = notifications[index];
|
||||||
|
if (currentNotification)
|
||||||
|
{
|
||||||
|
std::cout << std::left
|
||||||
|
<< std::setw(6) << currentIndex
|
||||||
|
<< std::setw(15) << currentNotification->getId()
|
||||||
|
<< std::setw(30) << currentNotification->getTitle()
|
||||||
|
<< std::setw(25) << currentNotification->getCreatedAt().toString()
|
||||||
|
<< std::endl;
|
||||||
|
indexedNotifications.insert(currentIndex, currentNotification);
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int selectedIndex;
|
||||||
|
std::cout << "Select notification: ";
|
||||||
|
util::read(selectedIndex);
|
||||||
|
if (!indexedNotifications.containsKey(selectedIndex))
|
||||||
|
{
|
||||||
|
std::cout << "Invalid selection." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return indexedNotifications[selectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void displayNotification(const Notification* notification)
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!notification)
|
||||||
|
{
|
||||||
|
std::cout << "Notification not found." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cout << "Notification Details" << std::endl;
|
||||||
|
std::cout << "ID : " << notification->getId() << std::endl;
|
||||||
|
std::cout << "Title : " << notification->getTitle() << std::endl;
|
||||||
|
std::cout << "Timestamp : " << notification->getCreatedAt().toString() << std::endl;
|
||||||
|
std::cout << "Message : " << notification->getMessage() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void viewAndDeleteNotification(Controller& controller)
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
auto notifications = controller.getNotifications();
|
||||||
|
const Notification* selectedNotification = selectNotification(notifications);
|
||||||
|
if (!selectedNotification)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to display notification!";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
displayNotification(selectedNotification);
|
||||||
|
controller.deleteNotification(selectedNotification->getId());
|
||||||
|
util::pressEnter();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user