Skip to content

Commit

Permalink
BAH-3860 | Enhancements in Appointments module (#332)
Browse files Browse the repository at this point in the history
* Bindu |Change the update error message (#309)

* Phani | A-1206828243895868 | Remove debouncing and add API cancellation for Appointment Patient Search (#323)

* Phani : Add logic to Cancel API calls in-flight

* Phani : Fix tests

* Phani : Remove debounce related code

* Phani : Add method to create disabled dropdown options

* A-1207131329891848 | Filtering on Awaiting Appointments should query the backend (#330)

* fix. awaiting appointments search post API update

* add. filter for awaiting appointments for bulk waitlists

* fix. existing tests after appointments earch API update

* add. test for checking appointments earch getting called when a filter is selected

* fix. awaiting appointment list after applying filter (#331)

* BAH-3860 | Fix build failure

* BAH-3860 | remove test

---------

Co-authored-by: Himabindu T <tbindu@thoughtworks.com>
Co-authored-by: Phanindra-tw <v.tadikonda@thoughtworks.com>
  • Loading branch information
3 people committed Jun 11, 2024
1 parent 49f1693 commit 2ef2ef2
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 45 deletions.
3 changes: 2 additions & 1 deletion i18n/appointments/locale_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@
"RECURRENCE_WEEKDAYS_ERROR_MESSAGE": "Please select the day(s)",
"NO_CONTENT_ERROR_MESSAGE": "Selected days do not fall under the end date selected",
"UNEXPECTED_SERVICE_ERROR": "There was an unexpected issue on the server. Please try again",
"APPOINTMENT_SEARCH_TIME_ERROR": "Connection timed out. The request took too long to complete.",
"PRIORITY_ERROR_MESSAGE": "Please select appointment category",
"STATUS_ERROR_MESSAGE": "Please select appointment status",
"APPOINTMENT_CANCEL_CONFIRMATION_TEXT": "You will lose appointment details. Do you want to discard these changes?",
Expand Down Expand Up @@ -257,7 +258,7 @@
"NUMBER_OF_OCCURRENCE_LABEL": "# of occurrences",
"APPOINTMENT_UPDATE_CONFIRMATION_TITLE": "Kindly Confirm",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_RECURRING_APPOINTMENT": "This will update the details of the entire appointment series. This cannot be reversed!",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_SINGLE_APPOINTMENT": "This will update the details of the selected appointment. This cannot be reversed!",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_SINGLE_APPOINTMENT": "This will update the details of the selected appointment",
"APPOINTMENT_UPDATE_CONFIRMATION_NO": "No, go back",
"APPOINTMENT_UPDATE_CONFIRMATION_YES": "Yes, I confirm",
"APPOINTMENT_SAVE_SUCCESS_TEXT": "The new appointment for the patient {patientDetails} has been saved.",
Expand Down
3 changes: 1 addition & 2 deletions src/controllers/manage/appointmentsCreateController.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ angular.module('bahmni.appointments')
var patientSearchURL = appService.getAppDescriptor().getConfigValue('patientSearchUrl');
var loginLocationUuid = sessionService.getLoginLocationUuid();
$scope.minCharLengthToTriggerPatientSearch = appService.getAppDescriptor().getConfigValue('minCharLengthToTriggerPatientSearch') || 3;

$scope.maxAppointmentProviders = appService.getAppDescriptor().getConfigValue("maxAppointmentProviders") || 1;

var isProviderNotAvailableForAppointments = function (selectedProvider) {
Expand Down Expand Up @@ -158,7 +157,7 @@ angular.module('bahmni.appointments')

$scope.onSelectPatient = function (data) {
$scope.appointment.patient = data;
return spinner.forPromise(appointmentsService.search({patientUuid: data.uuid}).then(function (oldAppointments) {
return spinner.forPromise(appointmentsService.search({patientUuids: [data.uuid]}).then(function (oldAppointments) {
$scope.patientAppointments = oldAppointments.data;
}));
};
Expand Down
13 changes: 11 additions & 2 deletions src/controllers/manage/appointmentsFilterController.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';

angular.module('bahmni.appointments')
.controller('AppointmentsFilterController', ['$scope', '$state', '$rootScope', '$q', '$translate', 'appointmentsServiceService', 'spinner', 'ivhTreeviewMgr', 'providerService', 'appService', 'locationService',
function ($scope, $state, $rootScope, $q, $translate, appointmentsServiceService, spinner, ivhTreeviewMgr, providerService, appService, locationService) {
.controller('AppointmentsFilterController', ['$scope', '$state', '$rootScope', '$q', '$translate', 'appointmentsServiceService', 'spinner', 'ivhTreeviewMgr', 'providerService', 'appService', 'locationService', 'appointmentsService',
function ($scope, $state, $rootScope, $q, $translate, appointmentsServiceService, spinner, ivhTreeviewMgr, providerService, appService, locationService, appointmentsService) {
var init = function () {
$scope.isSpecialityEnabled = appService.getAppDescriptor().getConfigValue('enableSpecialities');
$scope.isServiceTypeEnabled = appService.getAppDescriptor().getConfigValue('enableServiceTypes');
Expand Down Expand Up @@ -254,6 +254,15 @@ angular.module('bahmni.appointments')
$state.params.filterParams.statusList = _.map($scope.selectedStatusList, function (status) {
return status.value;
});
const AWAITING_APPOINTMENTS_TAB_NAME = "awaitingappointments";
if($state.current.tabName === AWAITING_APPOINTMENTS_TAB_NAME) {
let payload = $state.params.filterParams;
payload.withoutDates = true;
spinner.forPromise(appointmentsService.search(payload).then(function (response) {
$rootScope.appointmentsData = response.data;
$rootScope.$broadcast("awaitingFilterResponse", response);
}));
}
};

$scope.isFilterApplied = function () {
Expand Down
21 changes: 13 additions & 8 deletions src/controllers/manage/list/appointmentsListViewController.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ angular.module('bahmni.appointments')
var autoRefreshIntervalInSeconds = parseInt(appService.getAppDescriptor().getConfigValue('autoRefreshIntervalInSeconds'));
var enableAutoRefresh = !isNaN(autoRefreshIntervalInSeconds);
var autoRefreshStatus = true;
const APPOINTMENT_STATUS_WAITLIST = $scope.disableDatesForWaitListAppointment ?
{"isDatelessAppointments": true} :
{"status" : "WaitList"}
const APPOINTMENT_STATUS_WAITLIST = {
"withoutDates": true
}
const APPOINTMENTS_TAB_NAME = "appointments";
const AWAITING_APPOINTMENTS_TAB_NAME = "awaitingappointments";
const SECONDS_TO_MILLISECONDS_FACTOR = 1000;
Expand Down Expand Up @@ -75,10 +75,11 @@ angular.module('bahmni.appointments')
autoRefreshStatus = false;
if($scope.getCurrentTabName() === APPOINTMENTS_TAB_NAME)
return appointmentsService.getAllAppointments(params)
.then((response) => updateAppointments(response));
else
return appointmentsService.search(APPOINTMENT_STATUS_WAITLIST)
.then((response) => updateAppointments(response));
.then((response) => updateAppointments(response));
else
return appointmentsService.search( prefilledPatient ? { patientUuids: [prefilledPatient] } : APPOINTMENT_STATUS_WAITLIST)
.then((response) => updateAppointments(response))
.catch((error) => messagingService.showMessage('error', 'APPOINTMENT_SEARCH_TIME_ERROR'));
};

var updateAppointments = function (response){
Expand Down Expand Up @@ -120,7 +121,7 @@ angular.module('bahmni.appointments')
}

var setAppointmentsInPatientSearch = function (patientUuid) {
appointmentsService.search({patientUuid: patientUuid}).then(function (response) {
appointmentsService.search({patientUuids: [patientUuid]}).then(function (response) {
var appointmentsInDESCOrderBasedOnStartDateTime = _.sortBy(response.data, "startDateTime").reverse();
setFilteredAppointmentsInPatientSearch(appointmentsInDESCOrderBasedOnStartDateTime);
});
Expand Down Expand Up @@ -330,6 +331,10 @@ angular.module('bahmni.appointments')
$scope.reverseSort = !$scope.reverseSort;
};

$rootScope.$on('awaitingFilterResponse', function (event, response) {
$scope.filteredAppointments = response.data;
});

$scope.printPage = function () {
var printTemplateUrl = appService.getAppDescriptor().getConfigValue("printListViewTemplateUrl") || 'views/manage/list/defaultListPrint.html';
printer.print(printTemplateUrl, {
Expand Down
2 changes: 1 addition & 1 deletion src/directives/patientSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ angular.module('bahmni.appointments')

$scope.onSelectPatient = function (data) {
$state.params.patient = data;
spinner.forPromise(appointmentsService.search({patientUuid: data.uuid}).then(function (oldAppointments) {
spinner.forPromise(appointmentsService.search({patientUuids: [data.uuid]}).then(function (oldAppointments) {
var appointmentInDESCOrderBasedOnStartDateTime = _.sortBy(oldAppointments.data, "startDateTime").reverse();
$scope.onSearch(appointmentInDESCOrderBasedOnStartDateTime);
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ describe("AppointmentsCreateController", function () {
$scope.patientAppointments = undefined;
var patientUuid = 'uuid';
appointmentContext = {appointment: {patient:{uuid: patientUuid}}};
var appointmentSearchParams = {patientUuid: patientUuid};
var appointmentSearchParams = {patientUuids: [patientUuid]};
createController();

expect(appointmentsService.search).toHaveBeenCalledWith(appointmentSearchParams);
Expand Down
20 changes: 19 additions & 1 deletion test/controllers/manage/appointmentsFilterController.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

describe('AppointmentsFilterController', function () {
var controller, scope, state, appService, appDescriptor, appointmentsServiceService, ivhTreeviewMgr, q, translate;
var controller, scope, state, appService, appDescriptor, appointmentsServiceService, ivhTreeviewMgr, q, translate, appointmentsService;
var locationService = jasmine.createSpyObj('locationService', ['getAllByTag']);
var providerService = jasmine.createSpyObj('providerService', ['list']);
var appService = jasmine.createSpyObj('appService', ['getAppDescriptor']);
Expand Down Expand Up @@ -93,6 +93,7 @@ describe('AppointmentsFilterController', function () {
appService = jasmine.createSpyObj('appService', ['getAppDescriptor']);
appDescriptor = jasmine.createSpyObj('appDescriptor', ['getConfigValue']);
appointmentsServiceService = jasmine.createSpyObj('appointmentsServiceService', ['getAllServicesWithServiceTypes']);
appointmentsService = jasmine.createSpyObj('appointmentsService', ['search']);
ivhTreeviewMgr = jasmine.createSpyObj('ivhTreeviewMgr', ['deselectAll', 'selectEach', 'collapseRecursive']);
translate = jasmine.createSpyObj('$translate', ['instant']);
appService.getAppDescriptor.and.returnValue(appDescriptor);
Expand All @@ -115,6 +116,7 @@ describe('AppointmentsFilterController', function () {
$scope: scope,
appService: appService,
appointmentsServiceService: appointmentsServiceService,
appointmentsService: appointmentsService,
$state: state,
ivhTreeviewMgr: ivhTreeviewMgr,
$q: q,
Expand Down Expand Up @@ -800,4 +802,20 @@ describe('AppointmentsFilterController', function () {
createController();
expect(scope.providers.length).toBe(2)
});

it("should make appointments search call when in awaiting appointments tab when filters are clicked", function() {
q.all.and.returnValue(specUtil.simplePromise([servicesWithTypes, providers, locations]));
createController();
state.current.tabName = "awaitingappointments";
appointmentsService.search.and.returnValue(specUtil.simplePromise({data: []}));
scope.applyFilter();
expect(appointmentsService.search).toHaveBeenCalledWith({
serviceUuids: [],
serviceTypeUuids : [],
providerUuids: [],
locationUuids: [],
statusList: [],
withoutDates: true
});
});
});
4 changes: 2 additions & 2 deletions test/directives/patientSearch.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe("Patient Search", function () {
var patient = {uuid: 'patientUuid'};
compiledScope.onSelectPatient(patient);
expect(state.params.patient).toEqual(patient);
expect(appointmentsService.search).toHaveBeenCalledWith({patientUuid: patient.uuid});
expect(appointmentsService.search).toHaveBeenCalledWith({patientUuids: [patient.uuid]});
expect(scope.displaySearchedPatient).toHaveBeenCalled();
});

Expand All @@ -90,7 +90,7 @@ describe("Patient Search", function () {
var element = createElement();
var compiledScope = element.isolateScope();
expect(compiledScope.patient).toBe(patient.givenName + " " + patient.familyName + " " + "(" + patient.identifier + ")");
expect(appointmentsService.search).toHaveBeenCalledWith({patientUuid: patient.uuid});
expect(appointmentsService.search).toHaveBeenCalledWith({patientUuids: [patient.uuid]});
expect(scope.displaySearchedPatient).toHaveBeenCalled();
});

Expand Down
2 changes: 1 addition & 1 deletion ui/i18n/appointments/locale_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
"NUMBER_OF_OCCURRENCE_LABEL": "# of occurrences",
"APPOINTMENT_UPDATE_CONFIRMATION_TITLE": "Kindly Confirm",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_RECURRING_APPOINTMENT": "This will update the details of the entire appointment series. This cannot be reversed!",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_SINGLE_APPOINTMENT": "This will update the details of the selected appointment. This cannot be reversed!",
"APPOINTMENT_UPDATE_CONFIRMATION_TEXT_SINGLE_APPOINTMENT": "This will update the details of the selected appointment.",
"APPOINTMENT_UPDATE_CONFIRMATION_NO": "No, go back",
"APPOINTMENT_UPDATE_CONFIRMATION_YES": "Yes, I confirm",
"APPOINTMENT_SAVE_SUCCESS_TEXT": "The new appointment for the patient {patientDetails} has been saved.",
Expand Down
2 changes: 1 addition & 1 deletion ui/react-components/api/patientApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const getPatientsByLocation = async (locationUuid, searchQuery, cancelTok
if (!axios.isCancel(error)) {
console.error(error);
}
return error;
return error.response;
}
};

Expand Down
24 changes: 1 addition & 23 deletions ui/react-components/api/patientApi.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,26 +145,4 @@ describe('Patient Api', () => {
expect(patient).toEqual(mockResponse);
});

it('should return cancelled Response', async () => {
let locationUuid = "locationUuid";
let searchQuery = "searchquery";
const source = mockAxios.CancelToken.source();
let expectedParams = {
cancelToken: source.token,
params: {
filterOnAllIdentifiers: true,
identifier: searchQuery,
loginLocationUuid: locationUuid,
q: searchQuery,
startIndex: 0
}
}
const promise = getPatientsByLocation(locationUuid, searchQuery, source.token);
source.cancel("Request Cancelled by user");
const response = await promise;
expect(mockAxios.get)
.toHaveBeenCalledWith(searchPatientUrl, expectedParams);
expect(mockAxios.isCancel(response)).toBeTruthy();
expect(response.message).toEqual("Request Cancelled by user");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const UpdateConfirmationModal = (props) => {
setOpen(false);
}
const body = <FormattedMessage id={'APPOINTMENT_UPDATE_CONFIRMATION_TEXT_SINGLE_APPOINTMENT'}
defaultMessage={'This will update the details of the selected appointment. This cannot be reversed!'}/>
defaultMessage={'This will update the details of the selected appointment.'}/>

const title=<FormattedMessage id={'APPOINTMENT_UPDATE_CONFIRMATION_TITLE'} defaultMessage={"Kindly Confirm"} />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Update Confirmation Modal ', () => {
it('should render update confirm modal closeIcon, title, body, yes and no buttons', () => {
const {getByText} = renderWithReactIntl(<UpdateConfirmationModal />);
getByText('Kindly Confirm');
getByText('This will update the details of the selected appointment. This cannot be reversed!');
getByText('This will update the details of the selected appointment.');
getByText('No, go back');
getByText('Yes, I confirm');
});
Expand Down

0 comments on commit 2ef2ef2

Please sign in to comment.