/
AppointmentController.java
203 lines (181 loc) · 11.5 KB
/
AppointmentController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package org.openmrs.module.appointments.web.controller;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.api.APIException;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.context.Context;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.model.AppointmentProvider;
import org.openmrs.module.appointments.model.AppointmentServiceDefinition;
import org.openmrs.module.appointments.model.AppointmentServiceType;
import org.openmrs.module.appointments.model.AppointmentStatus;
import org.openmrs.module.appointments.service.AppointmentServiceDefinitionService;
import org.openmrs.module.appointments.service.AppointmentsService;
import org.openmrs.module.appointments.util.DateUtil;
import org.openmrs.module.appointments.web.contract.*;
import org.openmrs.module.appointments.web.mapper.AppointmentMapper;
import org.openmrs.module.appointments.web.mapper.AppointmentServiceMapper;
import org.openmrs.module.webservices.rest.web.RestConstants;
import org.openmrs.module.webservices.rest.web.RestUtil;
import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@Controller
@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/appointment")
public class AppointmentController extends BaseRestController {
private Log log = LogFactory.getLog(this.getClass());
@Autowired
private AppointmentsService appointmentsService;
@Autowired
private AppointmentServiceDefinitionService appointmentServiceDefinitionService;
@Autowired
private AppointmentMapper appointmentMapper;
@Autowired
private AppointmentServiceMapper appointmentServiceMapper;
@RequestMapping(method = RequestMethod.GET, value = "all")
@ResponseBody
public List<AppointmentDefaultResponse> getAllAppointments(@RequestParam(value = "forDate", required = false) String forDate) throws ParseException {
List<Appointment> appointments = appointmentsService.getAllAppointments(DateUtil.convertToLocalDateFromUTC(forDate));
return appointmentMapper.constructResponse(appointments);
}
@RequestMapping( method = RequestMethod.POST, value = "search")
@ResponseBody
public List<AppointmentDefaultResponse> searchAppointments( @Valid @RequestBody AppointmentQuery searchQuery) throws IOException {
if(searchQuery.isWithoutDates()) {
List<Appointment> appointmentsWithoutDates = appointmentsService.searchAppointmentsWithoutDates();
return appointmentMapper.constructResponse(appointmentsWithoutDates);
}
Appointment appointment = appointmentMapper.mapQueryToAppointment(searchQuery);
if (searchQuery.getStatus() == null) {
appointment.setStatus(null);
}
List<Appointment> appointments = appointmentsService.search(appointment);
return appointmentMapper.constructResponse(appointments);
}
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<Object> saveAppointment(@Valid @RequestBody AppointmentRequest appointmentRequest){
try {
/**
* The above code has been done so because to make appointment save within a transaction boundary.
* calling appointmentMapper starts a transaction and persistent object is modified, which when
* appointmentService.validateAndSave() is called was being written to DB, as calling validateAndSave() will
* start another transaction, and before that the dirty persistent entity will be flushed to DB.
* appointmentMapper should be fixed and validateAndSave() signature should be changed.
*/
Appointment appointment = appointmentsService.validateAndSave(() -> appointmentMapper.fromRequest(appointmentRequest));
return new ResponseEntity<>(appointmentMapper.constructResponse(appointment), HttpStatus.OK);
} catch (Exception e) {
log.error("Runtime error while trying to create new appointment", e);
return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), HttpStatus.BAD_REQUEST);
}
}
@RequestMapping( method = RequestMethod.GET, value = "futureAppointmentsForServiceType")
@ResponseBody
public List<AppointmentDefaultResponse> getAllFututreAppointmentsForGivenServiceType(@RequestParam(value = "appointmentServiceTypeUuid", required = true) String serviceTypeUuid) {
AppointmentServiceType appointmentServiceType = appointmentServiceDefinitionService.getAppointmentServiceTypeByUuid(serviceTypeUuid);
List<Appointment> appointments = appointmentsService.getAllFutureAppointmentsForServiceType(appointmentServiceType);
return appointmentMapper.constructResponse(appointments);
}
@RequestMapping(method = RequestMethod.GET, value = "appointmentSummary")
@ResponseBody
public List<AppointmentsSummary> getAllAppointmentsSummary(@RequestParam(value = "startDate") String startDateString, @RequestParam(value = "endDate") String endDateString) throws ParseException {
List<AppointmentsSummary> appointmentsSummaryList = new ArrayList<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = DateUtil.convertToLocalDateFromUTC(startDateString);
Date endDate = DateUtil.convertToLocalDateFromUTC(endDateString);
List<AppointmentServiceDefinition> appointmentServiceDefinitions = appointmentServiceDefinitionService.getAllAppointmentServices(false);
for (AppointmentServiceDefinition appointmentServiceDefinition : appointmentServiceDefinitions) {
List<Appointment> appointmentsForService =
appointmentsService.getAppointmentsForService(
appointmentServiceDefinition, startDate, endDate,
Arrays.asList(
AppointmentStatus.Requested,
AppointmentStatus.Completed,
AppointmentStatus.Scheduled,
AppointmentStatus.CheckedIn,
AppointmentStatus.Missed));
Map<Date, List<Appointment>> appointmentsGroupedByDate =
appointmentsForService.stream().collect(Collectors.groupingBy(Appointment::getDateFromStartDateTime));
Map<String, DailyAppointmentServiceSummary> appointmentCountMap = new LinkedHashMap<>();
for (Map.Entry<Date, List<Appointment>> appointmentDateMap : appointmentsGroupedByDate.entrySet()) {
List<Appointment> appointments = appointmentDateMap.getValue();
Long missedAppointmentsCount = appointments.stream().filter(s-> s.getStatus().equals(AppointmentStatus.Missed)).count();
DailyAppointmentServiceSummary dailyAppointmentServiceSummary = new DailyAppointmentServiceSummary(
appointmentDateMap.getKey(), appointmentServiceDefinition.getUuid(), appointments.size(),Math.toIntExact(missedAppointmentsCount));
appointmentCountMap.put(simpleDateFormat.format(appointmentDateMap.getKey()), dailyAppointmentServiceSummary);
}
AppointmentsSummary appointmentsSummary = new AppointmentsSummary(appointmentServiceMapper.constructDefaultResponse(appointmentServiceDefinition), appointmentCountMap);
appointmentsSummaryList.add(appointmentsSummary);
}
return appointmentsSummaryList;
}
@RequestMapping(method = RequestMethod.POST, value="undoStatusChange/{appointmentUuid}")
@ResponseBody
public ResponseEntity<Object> undoStatusChange(@PathVariable("appointmentUuid")String appointmentUuid) throws ParseException {
try{
Appointment appointment = appointmentsService.getAppointmentByUuid(appointmentUuid);
if(appointment == null){
throw new RuntimeException("Appointment does not exist");
}
appointmentsService.undoStatusChange(appointment);
return new ResponseEntity<>(appointmentMapper.constructResponse(appointment), HttpStatus.OK);
} catch (RuntimeException e) {
log.error("Runtime error while trying to undo appointment status", e);
return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), HttpStatus.BAD_REQUEST);
}
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public AppointmentDefaultResponse getAppointmentByUuid(@RequestParam(value = "uuid") String uuid) {
Appointment appointment = appointmentsService.getAppointmentByUuid(uuid);
if(appointment == null) {
log.error("Invalid. Appointment does not exist. UUID - " + uuid);
throw new RuntimeException("Appointment does not exist");
}
return appointmentMapper.constructResponse(appointment);
}
@RequestMapping(method = RequestMethod.POST, value="/{appointmentUuid}/providerResponse")
@ResponseBody
public ResponseEntity<Object> updateAppointmentProviderResponse(@PathVariable("appointmentUuid")String appointmentUuid, @RequestBody AppointmentProviderDetail providerResponse) throws ParseException {
try {
Appointment appointment = appointmentsService.getAppointmentByUuid(appointmentUuid);
if(appointment == null){
throw new RuntimeException("Appointment does not exist");
}
AppointmentProvider appointmentProviderProvider = appointmentMapper.mapAppointmentProvider(providerResponse);
appointmentsService.updateAppointmentProviderResponse(appointmentProviderProvider);
return new ResponseEntity<>(HttpStatus.OK);
}catch (RuntimeException e) {
log.error("Runtime error while trying to update appointment provider response", e);
return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), HttpStatus.BAD_REQUEST);
}
}
//TODO write test
@RequestMapping(method = RequestMethod.POST, value="/{uuid}/reschedule")
@ResponseBody
public ResponseEntity<Object> rescheduleAppointment(@PathVariable("uuid") String prevAppointmentUuid,
@Valid @RequestBody AppointmentRequest appointmentRequest,
@RequestParam(value = "retainNumber", required = false, defaultValue = "false") boolean retainAppointmentNumber)
throws ParseException {
try {
appointmentRequest.setUuid(null);
Appointment appointment = appointmentMapper.fromRequest(appointmentRequest);
Appointment rescheduledAppointment = appointmentsService.reschedule(prevAppointmentUuid, appointment, false);
return new ResponseEntity<>(appointmentMapper.constructResponse(rescheduledAppointment), HttpStatus.OK);
} catch (RuntimeException e) {
log.error("Runtime error while trying to create new appointment", e);
return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), HttpStatus.BAD_REQUEST);
}
}
}