• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmrs / openmrs-core / 21885081110

10 Feb 2026 10:36PM UTC coverage: 65.419% (+0.1%) from 65.317%
21885081110

push

github

dkayiwa
TRUNK-6542 Editing observations should copy reference ranges

11 of 11 new or added lines in 1 file covered. (100.0%)

110 existing lines in 6 files now uncovered.

23798 of 36378 relevant lines covered (65.42%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.76
/api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.api.impl;
11

12
import org.apache.commons.lang3.time.DateUtils;
13
import org.hibernate.proxy.HibernateProxy;
14
import org.openmrs.CareSetting;
15
import org.openmrs.Concept;
16
import org.openmrs.ConceptClass;
17
import org.openmrs.Encounter;
18
import org.openmrs.DrugOrder;
19
import org.openmrs.Order;
20
import org.openmrs.OrderAttribute;
21
import org.openmrs.OrderAttributeType;
22
import org.openmrs.OrderFrequency;
23
import org.openmrs.OrderGroup;
24
import org.openmrs.OrderType;
25
import org.openmrs.GlobalProperty;
26
import org.openmrs.Patient;
27
import org.openmrs.Provider;
28
import org.openmrs.ReferralOrder;
29
import org.openmrs.Order.FulfillerStatus;
30
import org.openmrs.OrderGroupAttribute;
31
import org.openmrs.OrderGroupAttributeType;
32
import org.openmrs.TestOrder;
33
import org.openmrs.Visit;
34
import org.openmrs.api.APIException;
35
import org.openmrs.api.AmbiguousOrderException;
36
import org.openmrs.api.CannotDeleteObjectInUseException;
37
import org.openmrs.api.CannotStopDiscontinuationOrderException;
38
import org.openmrs.api.CannotStopInactiveOrderException;
39
import org.openmrs.api.CannotUnvoidOrderException;
40
import org.openmrs.api.EditedOrderDoesNotMatchPreviousException;
41
import org.openmrs.api.GlobalPropertyListener;
42
import org.openmrs.api.MissingRequiredPropertyException;
43
import org.openmrs.api.OrderContext;
44
import org.openmrs.api.OrderEntryException;
45
import org.openmrs.api.OrderNumberGenerator;
46
import org.openmrs.api.OrderService;
47
import org.openmrs.api.UnchangeableObjectException;
48
import org.openmrs.api.context.Context;
49
import org.openmrs.api.db.OrderDAO;
50
import org.openmrs.customdatatype.CustomDatatypeUtil;
51
import org.openmrs.order.OrderUtil;
52
import org.openmrs.parameter.OrderSearchCriteria;
53
import org.openmrs.util.ConfigUtil;
54
import org.openmrs.util.OpenmrsConstants;
55
import org.openmrs.util.OpenmrsUtil;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58
import org.springframework.transaction.annotation.Propagation;
59
import org.springframework.transaction.annotation.Transactional;
60
import org.springframework.util.StringUtils;
61

62
import java.lang.reflect.Field;
63
import java.util.ArrayList;
64
import java.util.Arrays;
65
import java.util.Calendar;
66
import java.util.Collections;
67
import java.util.Date;
68
import java.util.List;
69
import java.util.Locale;
70
import java.util.Set;
71

72
import static org.openmrs.Order.Action.DISCONTINUE;
73
import static org.openmrs.Order.Action.NEW;
74
import static org.openmrs.Order.Action.REVISE;
75

76
/**
77
 * Default implementation of the Order-related services class. This method should not be invoked by
78
 * itself. Spring injection is used to inject this implementation into the ServiceContext. Which
79
 * implementation is injected is determined by the spring application context file:
80
 * /metadata/api/spring/applicationContext.xml
81
 * 
82
 * @see org.openmrs.api.OrderService
83
 */
84
@Transactional
85
public class OrderServiceImpl extends BaseOpenmrsService implements OrderService, OrderNumberGenerator, GlobalPropertyListener {
86
        
87
        private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);
1✔
88
        
89
        private static final String ORDER_NUMBER_PREFIX = "ORD-";
90
        
91
        protected OrderDAO dao;
92
        
93
        private static OrderNumberGenerator orderNumberGenerator = null;
1✔
94

95
        public OrderServiceImpl() {
1✔
96
        }
1✔
97
        
98
        /**
99
         * @see org.openmrs.api.OrderService#setOrderDAO(org.openmrs.api.db.OrderDAO)
100
         */
101
        @Override
102
        public void setOrderDAO(OrderDAO dao) {
103
                this.dao = dao;
1✔
104
        }
1✔
105
        
106
        /**
107
         * @see org.openmrs.api.OrderService#saveOrder(org.openmrs.Order, org.openmrs.api.OrderContext)
108
         */
109
        @Override
110
        public synchronized Order saveOrder(Order order, OrderContext orderContext) throws APIException {
111
                return saveOrder(order, orderContext, false);
1✔
112
        }
113
        
114
        /**
115
         * @see org.openmrs.api.OrderService#saveOrderGroup(org.openmrs.OrderGroup)
116
         */
117
        @Override
118
        public OrderGroup saveOrderGroup(OrderGroup orderGroup) throws APIException {
119
                return saveOrderGroup(orderGroup, null);
1✔
120
        }
121

122
        /**
123
         * @see org.openmrs.api.OrderService#saveOrderGroup(org.openmrs.OrderGroup, org.openmrs.api.OrderContext)
124
         */
125
        @Override
126
        public OrderGroup saveOrderGroup(OrderGroup orderGroup, OrderContext orderContext) throws APIException {
127
                if (orderGroup.getId() == null) {
1✔
128
                        // an OrderGroup requires an encounter, which has a patient, so it
129
                        // is odd that OrderGroup has a patient field. There is no obvious
130
                        // reason why they should ever be different.
131
                        orderGroup.setPatient(orderGroup.getEncounter().getPatient());
1✔
132
                        CustomDatatypeUtil.saveAttributesIfNecessary(orderGroup);
1✔
133
                        dao.saveOrderGroup(orderGroup);
1✔
134
                }
135
                List<Order> orders = orderGroup.getOrders();
1✔
136
                for (Order order : orders) {
1✔
137
                        if (order.getId() == null) {
1✔
138
                                order.setEncounter(orderGroup.getEncounter());
1✔
139
                                Context.getOrderService().saveOrder(order, orderContext);
1✔
140
                        }
141
                }
1✔
142
                Set<OrderGroup> nestedGroups = orderGroup.getNestedOrderGroups();
1✔
143
                if (nestedGroups != null) {
1✔
144
                        for (OrderGroup nestedGroup : nestedGroups) {
1✔
145
                                Context.getOrderService().saveOrderGroup(nestedGroup, orderContext);
×
UNCOV
146
                        }
×
147
                }
148
                return orderGroup;
1✔
149
        }
150
        
151
        /**
152
         * @see org.openmrs.api.OrderService#saveOrder(org.openmrs.Order, org.openmrs.api.OrderContext)
153
         */
154
        @Override
155
        public synchronized Order saveRetrospectiveOrder(Order order, OrderContext orderContext) {
156
                return saveOrder(order, orderContext, true);
1✔
157
        }
158

159
        private Order saveOrder(Order order, OrderContext orderContext, boolean isRetrospective) {
160

161
                failOnExistingOrder(order);
1✔
162
                ensureDateActivatedIsSet(order);
1✔
163
                ensureConceptIsSet(order);
1✔
164
                ensureDrugOrderAutoExpirationDateIsSet(order);
1✔
165
                ensureOrderTypeIsSet(order,orderContext);
1✔
166
                ensureCareSettingIsSet(order,orderContext);
1✔
167
                failOnOrderTypeMismatch(order);
1✔
168
                
169
                // If isRetrospective is false, but the dateActivated is prior to the current date, set isRetrospective to true
170
                if (!isRetrospective) {
1✔
171
                        Date dateActivated = order.getDateActivated();
1✔
172
                        Date currentDate = new Date();
1✔
173
                        isRetrospective = !dateActivated.after(currentDate) && !DateUtils.isSameDay(dateActivated, currentDate);
1✔
174
                }
175
                
176
                Order previousOrder = order.getPreviousOrder();
1✔
177
                if (REVISE == order.getAction()) {
1✔
178
                        if (previousOrder == null) {
1✔
179
                                throw new MissingRequiredPropertyException("Order.previous.required", (Object[]) null);
1✔
180
                        }
181
                        stopOrder(previousOrder, aMomentBefore(order.getDateActivated()), isRetrospective);
1✔
182
                } else if (DISCONTINUE == order.getAction()) {
1✔
183
                        discontinueExistingOrdersIfNecessary(order, isRetrospective);
1✔
184
                }
185
                
186
                if (previousOrder != null) {
1✔
187
                        //concept should be the same as on previous order, same applies to drug for drug orders
188
                        if (NEW != order.getAction() && !order.hasSameOrderableAs(previousOrder)) {
1✔
189
                                throw new EditedOrderDoesNotMatchPreviousException("Order.orderable.doesnot.match");
1✔
190
                        } else if (!order.getOrderType().equals(previousOrder.getOrderType())) {
1✔
191
                                throw new EditedOrderDoesNotMatchPreviousException("Order.type.doesnot.match");
1✔
192
                        } else if (!order.getCareSetting().equals(previousOrder.getCareSetting())) {
1✔
193
                                throw new EditedOrderDoesNotMatchPreviousException("Order.care.setting.doesnot.match");
1✔
194
                        } else if (!getActualType(order).equals(getActualType(previousOrder))) {
1✔
195
                                throw new EditedOrderDoesNotMatchPreviousException("Order.class.doesnot.match");
1✔
196
                        }
197
                }
198
                
199
                if (DISCONTINUE != order.getAction()) {
1✔
200
                        Date asOfDate = new Date();
1✔
201
                        if (isRetrospective) {
1✔
202
                                asOfDate = order.getDateActivated();
1✔
203
                        }
204
                        List<Order> activeOrders = getActiveOrders(order.getPatient(), null, order.getCareSetting(), asOfDate);
1✔
205
                        List<String> parallelOrders = Collections.emptyList();
1✔
206
                        if (orderContext != null && orderContext.getAttribute(PARALLEL_ORDERS) != null) {
1✔
207
                                parallelOrders = Arrays.asList((String[]) orderContext.getAttribute(PARALLEL_ORDERS));
1✔
208
                        }
209
                        for (Order activeOrder : activeOrders) {
1✔
210
                                //Reject if there is an active drug order for the same orderable with overlapping schedule
211
                                if (!parallelOrders.contains(activeOrder.getUuid())
1✔
212
                                        && areDrugOrdersOfSameOrderableAndOverlappingSchedule(order, activeOrder)) {
1✔
213
                                        throw new AmbiguousOrderException("Order.cannot.have.more.than.one");
1✔
214
                                }
215
                        }
1✔
216
                }
217
                return saveOrderInternal(order, orderContext);
1✔
218
        }
219

220
        private void failOnExistingOrder(Order order) {
221
                if (order.getOrderId() != null) {
1✔
222
                        throw new UnchangeableObjectException("Order.cannot.edit.existing");
1✔
223
                }
224
        }
1✔
225

226
        private void ensureDateActivatedIsSet(Order order) {
227
                if (order.getDateActivated() == null) {
1✔
228
                        order.setDateActivated(new Date());
1✔
229
                }
230
        }
1✔
231

232
        private void ensureConceptIsSet(Order order) {
233
                Concept concept = order.getConcept();
1✔
234
                if (concept == null && isDrugOrder(order)) {
1✔
235
                        DrugOrder drugOrder = (DrugOrder) order;
1✔
236
                        if (drugOrder.getDrug() != null) {
1✔
237
                                concept = drugOrder.getDrug().getConcept();
×
UNCOV
238
                                drugOrder.setConcept(concept);
×
239
                        } else {
240
                                if (drugOrder.isNonCodedDrug()) {
1✔
241
                                        concept = getNonCodedDrugConcept();
1✔
242
                                        drugOrder.setConcept(concept);
1✔
243
                                }
244
                        }
245
                }
246
                if (concept == null) {
1✔
UNCOV
247
                        throw new MissingRequiredPropertyException("Order.concept.required");
×
248
                }
249
        }
1✔
250

251
        private void ensureDrugOrderAutoExpirationDateIsSet(Order order) {
252
                if (isDrugOrder(order)) {
1✔
253
                        ((DrugOrder) order).setAutoExpireDateBasedOnDuration();
1✔
254
                }
255
        }
1✔
256

257
        private void ensureOrderTypeIsSet(Order order, OrderContext orderContext) {
258
                if (order.getOrderType() != null) {
1✔
259
                        return;
1✔
260
                }
261
                OrderType orderType = null;
1✔
262
                if (orderContext != null) {
1✔
263
                        orderType = orderContext.getOrderType();
1✔
264
                }
265
                if (orderType == null) {
1✔
266
                        orderType = getOrderTypeByConcept(order.getConcept());
1✔
267
                }
268
                if (orderType == null && order instanceof DrugOrder) {
1✔
269
                        orderType = Context.getOrderService().getOrderTypeByUuid(OrderType.DRUG_ORDER_TYPE_UUID);
1✔
270
                }
271
                if (orderType == null && order instanceof TestOrder) {
1✔
272
                        orderType = Context.getOrderService().getOrderTypeByUuid(OrderType.TEST_ORDER_TYPE_UUID);
1✔
273
                }
274
                if (orderType == null && order instanceof ReferralOrder) {
1✔
UNCOV
275
                        orderType = Context.getOrderService().getOrderTypeByUuid(OrderType.REFERRAL_ORDER_TYPE_UUID);
×
276
                }
277
                if (orderType == null) {
1✔
278
                        throw new OrderEntryException("Order.type.cannot.determine");
1✔
279
                }
280
                Order previousOrder = order.getPreviousOrder();
1✔
281
                if (previousOrder != null && !orderType.equals(previousOrder.getOrderType())) {
1✔
UNCOV
282
                        throw new OrderEntryException("Order.type.does.not.match");
×
283
                }
284
                order.setOrderType(orderType);
1✔
285
        }
1✔
286

287
        private void ensureCareSettingIsSet(Order order, OrderContext orderContext) {
288
                if (order.getCareSetting() != null) {
1✔
289
                        return;
1✔
290
                }
291
                CareSetting careSetting = null;
1✔
292
                if (orderContext != null) {
1✔
293
                        careSetting = orderContext.getCareSetting();
1✔
294
                }
295
                Order previousOrder = order.getPreviousOrder();
1✔
296
                if (careSetting == null || (previousOrder != null && !careSetting.equals(previousOrder.getCareSetting()))) {
1✔
UNCOV
297
                        throw new OrderEntryException("Order.care.cannot.determine");
×
298
                }
299
                order.setCareSetting(careSetting);
1✔
300
        }
1✔
301

302
        private void failOnOrderTypeMismatch(Order order) {
303
                if (!order.getOrderType().getJavaClass().isAssignableFrom(order.getClass())) {
1✔
304
                        throw new OrderEntryException("Order.type.class.does.not.match", new Object[] {
×
UNCOV
305
                                        order.getOrderType().getJavaClass(), order.getClass().getName() });
×
306
                }
307
        }
1✔
308

309
        private boolean areDrugOrdersOfSameOrderableAndOverlappingSchedule(Order firstOrder, Order secondOrder) {
310
                return firstOrder.hasSameOrderableAs(secondOrder)
1✔
311
                        && !OpenmrsUtil.nullSafeEquals(firstOrder.getPreviousOrder(), secondOrder)
1✔
312
                        && OrderUtil.checkScheduleOverlap(firstOrder, secondOrder)
1✔
313
                        && firstOrder.getOrderType().equals(
1✔
314
                            Context.getOrderService().getOrderTypeByUuid(OrderType.DRUG_ORDER_TYPE_UUID));
1✔
315
        }
316

317
        private boolean isDrugOrder(Order order) {
318
                return DrugOrder.class.isAssignableFrom(getActualType(order));
1✔
319
        }
320

321
        
322
        /**
323
         * To support MySQL datetime values (which are only precise to the second) we subtract one
324
         * second. Eventually we may move this method and enhance it to subtract the smallest moment the
325
         * underlying database will represent.
326
         * 
327
         * @param date
328
         * @return one moment before date
329
         */
330
        private Date aMomentBefore(Date date) {
331
                return DateUtils.addSeconds(date, -1);
1✔
332
        }
333
        
334
        private Order saveOrderInternal(Order order, OrderContext orderContext) {
335
                if (order.getOrderId() == null) {
1✔
336
                        if (order.getOrderNumber() == null) {
1✔
337
                                setProperty(order, "orderNumber", getOrderNumberGenerator().getNewOrderNumber(orderContext));
1✔
338
                        }
339
                                
340
                        //DC orders should auto expire upon creating them
341
                        if (DISCONTINUE == order.getAction()) {
1✔
342
                                order.setAutoExpireDate(order.getDateActivated());
1✔
343
                        } else if (order.getAutoExpireDate() != null) {
1✔
344
                                Calendar cal = Calendar.getInstance();
1✔
345
                                cal.setTime(order.getAutoExpireDate());
1✔
346
                                int hours = cal.get(Calendar.HOUR_OF_DAY);
1✔
347
                                int minutes = cal.get(Calendar.MINUTE);
1✔
348
                                int seconds = cal.get(Calendar.SECOND);
1✔
349
                                cal.get(Calendar.MILLISECOND);
1✔
350
                                //roll autoExpireDate to end of day (23:59:59) if no time portion is specified
351
                                if (hours == 0 && minutes == 0 && seconds == 0) {
1✔
352
                                        cal.set(Calendar.HOUR_OF_DAY, 23);
1✔
353
                                        cal.set(Calendar.MINUTE, 59);
1✔
354
                                        cal.set(Calendar.SECOND, 59);
1✔
355
                                        // the OpenMRS database is only precise to the second
356
                                        cal.set(Calendar.MILLISECOND, 0);
1✔
357
                                        order.setAutoExpireDate(cal.getTime());
1✔
358
                                }
359
                        }
360
                }
361
                
362
                return dao.saveOrder(order);
1✔
363
        }
364
        
365
        private void setProperty(Order order, String propertyName, Object value) {
366
                Boolean isAccessible = null;
1✔
367
                Field field = null;
1✔
368
                try {
369
                        field = Order.class.getDeclaredField(propertyName);
1✔
370
                        field.setAccessible(true);
1✔
371
                        field.set(order, value);
1✔
372
                }
373
                catch (Exception e) {
×
UNCOV
374
                        throw new APIException("Order.failed.set.property", new Object[] { propertyName, order }, e);
×
375
                }
376
                finally {
377
                        if (field != null && isAccessible != null) {
1✔
UNCOV
378
                                field.setAccessible(isAccessible);
×
379
                        }
380
                }
381
        }
1✔
382
        
383
        /**
384
         * Gets the configured order number generator, if none is specified, it defaults to an instance
385
         * if this class
386
         * 
387
         * @return
388
         */
389
        private OrderNumberGenerator getOrderNumberGenerator() {
390
                if (orderNumberGenerator == null) {
1✔
391
                        String generatorBeanId = Context.getAdministrationService().getGlobalProperty(
1✔
392
                            OpenmrsConstants.GP_ORDER_NUMBER_GENERATOR_BEAN_ID);
393
                        if (StringUtils.hasText(generatorBeanId)) {
1✔
394
                                orderNumberGenerator = Context.getRegisteredComponent(generatorBeanId, OrderNumberGenerator.class);
1✔
395
                                log.info("Successfully set the configured order number generator");
1✔
396
                        } else {
397
                                orderNumberGenerator = this;
1✔
398
                                log.info("Setting default order number generator");
1✔
399
                        }
400
                }
401
                
402
                return orderNumberGenerator;
1✔
403
        }
404
        
405
        /**
406
         * If this is a discontinue order, ensure that the previous order is discontinued. If a
407
         * previousOrder is present, then ensure this is discontinued. If no previousOrder is present,
408
         * then try to find a previousOrder and discontinue it. If cannot find a previousOrder, throw
409
         * exception
410
         * 
411
         * @param order
412
         * @param isRetrospective
413
         */
414
        //Ignore and return if this is not an order to discontinue
415
        private void discontinueExistingOrdersIfNecessary(Order order, Boolean isRetrospective) {
416
                if (DISCONTINUE != order.getAction()) {
1✔
UNCOV
417
                        return;
×
418
                }
419
                
420
                //Mark previousOrder as discontinued if it is not already
421
                Order previousOrder = order.getPreviousOrder();
1✔
422
                if (previousOrder != null) {
1✔
423
                        stopOrder(previousOrder, aMomentBefore(order.getDateActivated()), isRetrospective);
1✔
424
                        return;
1✔
425
                }
426
                
427
                //Mark first order found corresponding to this DC order as discontinued.
428
                Date asOfDate = null;
1✔
429
                if (isRetrospective) {
1✔
430
                        asOfDate = order.getDateActivated();
1✔
431
                }
432
                List<? extends Order> orders = getActiveOrders(order.getPatient(), order.getOrderType(), order.getCareSetting(),
1✔
433
                    asOfDate);
434
                boolean isDrugOrderAndHasADrug = isDrugOrder(order)
1✔
435
                        && (((DrugOrder) order).getDrug() != null || ((DrugOrder) order).isNonCodedDrug());
1✔
436
                Order orderToBeDiscontinued = null;
1✔
437
                for (Order activeOrder : orders) {
1✔
438
                        if (!getActualType(order).equals(getActualType(activeOrder))) {
1✔
UNCOV
439
                                continue;
×
440
                        }
441
                        //For drug orders, the drug must match if the order has a drug
442
                        if (isDrugOrderAndHasADrug) {
1✔
443
                                Order existing = order.hasSameOrderableAs(activeOrder) ? activeOrder : null;
1✔
444
                                if (existing != null) {
1✔
445
                                        if (orderToBeDiscontinued == null) {
1✔
446
                                                orderToBeDiscontinued = existing;
1✔
447
                                        } else {
448
                                                throw new AmbiguousOrderException("Order.discontinuing.ambiguous.orders");
1✔
449
                                        }
450
                                }
451
                        } else if (activeOrder.getConcept().equals(order.getConcept())) {
1✔
452
                                if (orderToBeDiscontinued == null) {
1✔
453
                                        orderToBeDiscontinued = activeOrder;
1✔
454
                                } else {
455
                                        throw new AmbiguousOrderException("Order.discontinuing.ambiguous.orders");
1✔
456
                                }
457
                        }
458
                }
1✔
459
                if (orderToBeDiscontinued != null) {
1✔
460
                        order.setPreviousOrder(orderToBeDiscontinued);
1✔
461
                        stopOrder(orderToBeDiscontinued, aMomentBefore(order.getDateActivated()), isRetrospective);
1✔
462
                }
463
        }
1✔
464
        
465
        /**
466
         * Returns the class object of the specified persistent object returning the actual persistent
467
         * class in case it is a hibernate proxy
468
         *
469
         * @param persistentObject
470
         * @return the Class object
471
         */
472
        private Class<?> getActualType(Object persistentObject) {
473
                Class<?> type = persistentObject.getClass();
1✔
474
                if (persistentObject instanceof HibernateProxy) {
1✔
UNCOV
475
                        type = ((HibernateProxy) persistentObject).getHibernateLazyInitializer().getPersistentClass();
×
476
                }
477
                return type;
1✔
478
        }
479
        
480
        /**
481
         * @see org.openmrs.api.OrderService#purgeOrder(org.openmrs.Order)
482
         */
483
        @Override
484
        public void purgeOrder(Order order) throws APIException {
485
                purgeOrder(order, false);
1✔
486
        }
1✔
487
        
488
        /**
489
         * @see org.openmrs.api.OrderService#purgeOrder(Order)
490
         */
491
        @Override
492
        public void purgeOrder(Order order, boolean cascade) throws APIException {
493
                if (cascade) {
1✔
494
                        dao.deleteObsThatReference(order);
1✔
495
                }
496
                
497
                dao.deleteOrder(order);
1✔
498
        }
1✔
499
        
500
        /**
501
         * @see org.openmrs.api.OrderService#voidOrder(org.openmrs.Order, java.lang.String)
502
         */
503
        @Override
504
        public Order voidOrder(Order order, String voidReason) throws APIException {
505
                if (!StringUtils.hasLength(voidReason)) {
1✔
UNCOV
506
                        throw new IllegalArgumentException("voidReason cannot be empty or null");
×
507
                }
508
                
509
                Order previousOrder = order.getPreviousOrder();
1✔
510
                if (previousOrder != null && isDiscontinueOrReviseOrder(order)) {
1✔
511
                        setProperty(previousOrder, "dateStopped", null);
1✔
512
                }
513
                
514
                return saveOrderInternal(order, null);
1✔
515
        }
516
        
517
        /**
518
         * @see org.openmrs.api.OrderService#unvoidOrder(org.openmrs.Order)
519
         */
520
        @Override
521
        public Order unvoidOrder(Order order) throws APIException {
522
                Order previousOrder = order.getPreviousOrder();
1✔
523
                if (previousOrder != null && isDiscontinueOrReviseOrder(order)) {
1✔
524
                        if (!previousOrder.isActive()) {
1✔
525
                                final String action = DISCONTINUE == order.getAction() ? "discontinuation" : "revision";
1✔
526
                                throw new CannotUnvoidOrderException(action);
1✔
527
                        }
528
                        stopOrder(previousOrder, aMomentBefore(order.getDateActivated()), false);
1✔
529
                }
530
                
531
                return saveOrderInternal(order, null);
1✔
532
        }
533
        
534
        @Override
535
        public Order updateOrderFulfillerStatus(Order order, Order.FulfillerStatus orderFulfillerStatus, String fullFillerComment) {
536
                return updateOrderFulfillerStatus(order, orderFulfillerStatus, fullFillerComment, null);
1✔
537
        }
538

539
        @Override
540
        public Order updateOrderFulfillerStatus(Order order, FulfillerStatus orderFulfillerStatus, String fullFillerComment,
541
                                                                                        String accessionNumber) {
542

543
                if (orderFulfillerStatus != null) {
1✔
544
                        order.setFulfillerStatus(orderFulfillerStatus);
1✔
545
                }
546

547
                if (fullFillerComment != null) {
1✔
548
                        order.setFulfillerComment(fullFillerComment);
1✔
549
                }
550
        
551
                if (accessionNumber != null) {
1✔
552
                        order.setAccessionNumber(accessionNumber);
1✔
553
                }
554
                
555
                return saveOrderInternal(order, null);
1✔
556
        }
557
        
558
        /**
559
         * @see org.openmrs.api.OrderService#getOrder(java.lang.Integer)
560
         */
561
        @Override
562
        @Transactional(readOnly = true)
563
        public Order getOrder(Integer orderId) throws APIException {
564
                return dao.getOrder(orderId);
1✔
565
        }
566
        
567
        /**
568
         * @see OrderService#getOrders(org.openmrs.Patient, org.openmrs.CareSetting,
569
         *      org.openmrs.OrderType, boolean)
570
         */
571
        @Override
572
        public List<Order> getOrders(Patient patient, CareSetting careSetting, OrderType orderType, boolean includeVoided) {
573
                return this.getOrders(patient, null, careSetting, orderType, includeVoided);
1✔
574
        }
575
        
576
        /**
577
         * @see OrderService#getOrders(org.openmrs.Patient, org.openmrs.Visit, org.openmrs.CareSetting,
578
         *      org.openmrs.OrderType, boolean)
579
         */
580
        @Override
581
        public List<Order> getOrders(Patient patient, Visit visit, CareSetting careSetting, OrderType orderType, boolean includeVoided) {
582
                if (patient == null) {
1✔
583
                        throw new IllegalArgumentException("Patient is required");
1✔
584
                }
585
                if (careSetting == null) {
1✔
586
                        throw new IllegalArgumentException("CareSetting is required");
1✔
587
                }
588
                List<OrderType> orderTypes = null;
1✔
589
                if (orderType != null) {
1✔
590
                        orderTypes = new ArrayList<>();
1✔
591
                        orderTypes.add(orderType);
1✔
592
                        orderTypes.addAll(getSubtypes(orderType, true));
1✔
593
                }
594
                return dao.getOrders(patient, visit, careSetting, orderTypes, includeVoided, false);
1✔
595
        }
596
        
597
        /**
598
         * @see OrderService#getAllOrdersByPatient(org.openmrs.Patient)
599
         */
600
        @Override
601
        public List<Order> getAllOrdersByPatient(Patient patient) {
602
                if (patient == null) {
1✔
603
                        throw new IllegalArgumentException("Patient is required");
1✔
604
                }
605
                return dao.getOrders(patient, null, null, true, true);
1✔
606
        }
607
        
608
        @Override
609
        public List<Order> getOrders(OrderSearchCriteria orderSearchCriteria) {
610
                return dao.getOrders(orderSearchCriteria);
1✔
611
        }
612
        
613
        /**
614
         * @see org.openmrs.api.OrderService#getOrderByUuid(java.lang.String)
615
         */
616
        @Override
617
        @Transactional(readOnly = true)
618
        public Order getOrderByUuid(String uuid) throws APIException {
619
                return dao.getOrderByUuid(uuid);
1✔
620
        }
621
        
622
        /**
623
         * @see org.openmrs.api.OrderService#getDiscontinuationOrder(Order)
624
         */
625
        @Transactional(readOnly = true)
626
        @Override
627
        public Order getDiscontinuationOrder(Order order) throws APIException {
628
                return dao.getDiscontinuationOrder(order);
1✔
629
        }
630
        
631
        /**
632
         * @see org.openmrs.api.OrderService#getRevisionOrder(Order)
633
         */
634
        @Override
635
        public Order getRevisionOrder(Order order) throws APIException {
636
                return dao.getRevisionOrder(order);
1✔
637
        }
638
        
639
        /**
640
         * @see org.openmrs.api.OrderNumberGenerator#getNewOrderNumber(org.openmrs.api.OrderContext)
641
         * @param orderContext
642
         */
643
        @Override
644
        public String getNewOrderNumber(OrderContext orderContext) throws APIException {
645
                return ORDER_NUMBER_PREFIX + Context.getOrderService().getNextOrderNumberSeedSequenceValue();
1✔
646
        }
647
        
648
        /**
649
         * @see org.openmrs.api.OrderService#getOrderByOrderNumber(java.lang.String)
650
         */
651
        @Override
652
        @Transactional(readOnly = true)
653
        public Order getOrderByOrderNumber(String orderNumber) {
654
                return dao.getOrderByOrderNumber(orderNumber);
1✔
655
        }
656
        
657
        /**
658
         * @see org.openmrs.api.OrderService#getOrderHistoryByConcept(org.openmrs.Patient,
659
         *      org.openmrs.Concept)
660
         */
661
        @Override
662
        @Transactional(readOnly = true)
663
        public List<Order> getOrderHistoryByConcept(Patient patient, Concept concept) {
664
                if (patient == null || concept == null) {
1✔
665
                        throw new IllegalArgumentException("patient and concept are required");
1✔
666
                }
667
                List<Concept> concepts = new ArrayList<>();
1✔
668
                concepts.add(concept);
1✔
669
                
670
                List<Patient> patients = new ArrayList<>();
1✔
671
                patients.add(patient);
1✔
672
                
673
                return dao.getOrders(null, patients, concepts, new ArrayList<>(), new ArrayList<>());
1✔
674
        }
675
        
676
        /**
677
         * @see org.openmrs.api.OrderService#getNextOrderNumberSeedSequenceValue()
678
         */
679
        @Override
680
        @Transactional(propagation = Propagation.REQUIRES_NEW)
681
        public synchronized Long getNextOrderNumberSeedSequenceValue() {
682
                return dao.getNextOrderNumberSeedSequenceValue();
1✔
683
        }
684
        
685
        /**
686
         * @see org.openmrs.api.OrderService#getOrderHistoryByOrderNumber(java.lang.String)
687
         */
688
        @Override
689
        @Transactional(readOnly = true)
690
        public List<Order> getOrderHistoryByOrderNumber(String orderNumber) {
691
                List<Order> orders = new ArrayList<>();
1✔
692
                Order order = dao.getOrderByOrderNumber(orderNumber);
1✔
693
                while (order != null) {
1✔
694
                        orders.add(order);
1✔
695
                        order = order.getPreviousOrder();
1✔
696
                }
697
                return orders;
1✔
698
        }
699
        
700
        /**
701
         * @see org.openmrs.api.OrderService#getActiveOrders(org.openmrs.Patient, org.openmrs.OrderType,
702
         *      org.openmrs.CareSetting, java.util.Date)
703
         */
704
        @Override
705
        @Transactional(readOnly = true)
706
        public List<Order> getActiveOrders(Patient patient, OrderType orderType, CareSetting careSetting, Date asOfDate) {
707
                return this.getActiveOrders(patient, null, orderType, careSetting, asOfDate);
1✔
708
        }
709
        
710
        /**
711
         * @see org.openmrs.api.OrderService#getActiveOrders(org.openmrs.Patient, org.openmrs.Visit, org.openmrs.OrderType,
712
         *      org.openmrs.CareSetting, java.util.Date)
713
         */
714
        @Override
715
        @Transactional(readOnly = true)
716
        public List<Order> getActiveOrders(Patient patient, Visit visit, OrderType orderType, CareSetting careSetting, Date asOfDate) {
717
                if (patient == null) {
1✔
718
                        throw new IllegalArgumentException("Patient is required when fetching active orders");
1✔
719
                }
720
                if (asOfDate == null) {
1✔
721
                        asOfDate = new Date();
1✔
722
                }
723
                List<OrderType> orderTypes = null;
1✔
724
                if (orderType != null) {
1✔
725
                        orderTypes = new ArrayList<>();
1✔
726
                        orderTypes.add(orderType);
1✔
727
                        orderTypes.addAll(getSubtypes(orderType, true));
1✔
728
                }
729
                return dao.getActiveOrders(patient, visit, orderTypes, careSetting, asOfDate);
1✔
730
        }
731
        
732
        /**
733
         * @see org.openmrs.api.OrderService#getCareSetting(Integer)
734
         */
735
        @Override
736
        public CareSetting getCareSetting(Integer careSettingId) {
737
                return dao.getCareSetting(careSettingId);
1✔
738
        }
739
        
740
        /**
741
         * @see org.openmrs.api.OrderService#getCareSettingByUuid(String)
742
         */
743
        @Override
744
        public CareSetting getCareSettingByUuid(String uuid) {
745
                return dao.getCareSettingByUuid(uuid);
1✔
746
        }
747
        
748
        /**
749
         * @see org.openmrs.api.OrderService#getCareSettingByName(String)
750
         */
751
        @Override
752
        public CareSetting getCareSettingByName(String name) {
753
                return dao.getCareSettingByName(name);
1✔
754
        }
755
        
756
        /**
757
         * @see org.openmrs.api.OrderService#getCareSettings(boolean)
758
         */
759
        @Override
760
        public List<CareSetting> getCareSettings(boolean includeRetired) {
761
                return dao.getCareSettings(includeRetired);
1✔
762
        }
763
        
764
        /**
765
         * @see OrderService#getOrderTypeByName(String)
766
         */
767
        @Override
768
        public OrderType getOrderTypeByName(String orderTypeName) {
769
                return dao.getOrderTypeByName(orderTypeName);
1✔
770
        }
771
        
772
        /**
773
         * @see OrderService#getOrderFrequency(Integer)
774
         */
775
        @Override
776
        public OrderFrequency getOrderFrequency(Integer orderFrequencyId) {
777
                return dao.getOrderFrequency(orderFrequencyId);
1✔
778
        }
779
        
780
        /**
781
         * @see OrderService#getOrderFrequencyByUuid(String)
782
         */
783
        @Override
784
        public OrderFrequency getOrderFrequencyByUuid(String uuid) {
785
                return dao.getOrderFrequencyByUuid(uuid);
1✔
786
        }
787
        
788
        /**
789
         * @see OrderService#getOrderFrequencies(boolean)
790
         */
791
        @Override
792
        public List<OrderFrequency> getOrderFrequencies(boolean includeRetired) {
793
                return dao.getOrderFrequencies(includeRetired);
1✔
794
        }
795
        
796
        /**
797
         * @see OrderService#getOrderFrequencies(String, java.util.Locale, boolean, boolean)
798
         */
799
        @Override
800
        public List<OrderFrequency> getOrderFrequencies(String searchPhrase, Locale locale, boolean exactLocale,
801
                                                        boolean includeRetired) {
802
                if (searchPhrase == null) {
1✔
803
                        throw new IllegalArgumentException("searchPhrase is required");
1✔
804
                }
805
                return dao.getOrderFrequencies(searchPhrase, locale, exactLocale, includeRetired);
1✔
806
        }
807
        
808
        /**
809
         * @see org.openmrs.api.OrderService#discontinueOrder(org.openmrs.Order, org.openmrs.Concept,
810
         *      java.util.Date, org.openmrs.Provider, org.openmrs.Encounter)
811
         */
812
        @Override
813
        public Order discontinueOrder(Order orderToDiscontinue, Concept reasonCoded, Date discontinueDate, Provider orderer,
814
                                      Encounter encounter) {
815
                if (discontinueDate == null) {
1✔
816
                        discontinueDate = aMomentBefore(new Date());
1✔
817
                }
818
                stopOrder(orderToDiscontinue, discontinueDate, false);
1✔
819
                Order newOrder = orderToDiscontinue.cloneForDiscontinuing();
1✔
820
                newOrder.setOrderReason(reasonCoded);
1✔
821
                newOrder.setOrderer(orderer);
1✔
822
                newOrder.setEncounter(encounter);
1✔
823
                newOrder.setDateActivated(discontinueDate);
1✔
824
                return saveOrderInternal(newOrder, null);
1✔
825
        }
826
        
827
        /**
828
         * @see org.openmrs.api.OrderService#discontinueOrder(org.openmrs.Order, String, java.util.Date,
829
         *      org.openmrs.Provider, org.openmrs.Encounter)
830
         */
831
        @Override
832
        public Order discontinueOrder(Order orderToDiscontinue, String reasonNonCoded, Date discontinueDate, Provider orderer,
833
                                      Encounter encounter) {
834
                if (discontinueDate == null) {
1✔
835
                        discontinueDate = aMomentBefore(new Date());
1✔
836
                }
837
                stopOrder(orderToDiscontinue, discontinueDate, false);
1✔
838
                Order newOrder = orderToDiscontinue.cloneForDiscontinuing();
1✔
839
                newOrder.setOrderReasonNonCoded(reasonNonCoded);
1✔
840
                newOrder.setOrderer(orderer);
1✔
841
                newOrder.setEncounter(encounter);
1✔
842
                newOrder.setDateActivated(discontinueDate);
1✔
843
                return saveOrderInternal(newOrder, null);
1✔
844
        }
845
        
846
        private boolean isDiscontinueOrReviseOrder(Order order) {
847
                return DISCONTINUE == order.getAction() || REVISE == order.getAction();
1✔
848
        }
849
        
850
        /**
851
         * Make necessary checks, set necessary fields for discontinuing <code>orderToDiscontinue</code>
852
         * and save.
853
         *
854
         * @param orderToStop
855
         * @param discontinueDate
856
         */
857
        private void stopOrder(Order orderToStop, Date discontinueDate, boolean isRetrospective) {
858
                if (discontinueDate == null) {
1✔
UNCOV
859
                        discontinueDate = new Date();
×
860
                }
861
                if (discontinueDate.after(new Date())) {
1✔
862
                        throw new IllegalArgumentException("Discontinue date cannot be in the future");
1✔
863
                }
864
                if (DISCONTINUE == orderToStop.getAction()) {
1✔
865
                        throw new CannotStopDiscontinuationOrderException();
1✔
866
                }
867

868
                if (!ConfigUtil.getProperty(OpenmrsConstants.GP_ALLOW_SETTING_STOP_DATE_ON_INACTIVE_ORDERS, false)) {
1✔
869
                        if (isRetrospective && orderToStop.getDateStopped() != null) {
1✔
870
                                throw new CannotStopInactiveOrderException();
1✔
871
                        }
872
                        if (!isRetrospective && !orderToStop.isActive()) {
1✔
873
                                throw new CannotStopInactiveOrderException();
1✔
874
                        } else if (isRetrospective && !orderToStop.isActive(discontinueDate)) {
1✔
UNCOV
875
                                throw new CannotStopInactiveOrderException();
×
876
                        }
877
                }
878
                
879
                setProperty(orderToStop, "dateStopped", discontinueDate);
1✔
880
                saveOrderInternal(orderToStop, null);
1✔
881
        }
1✔
882
        
883
        /**
884
         * @see org.openmrs.api.OrderService#saveOrderFrequency(org.openmrs.OrderFrequency)
885
         */
886
        @Override
887
        public OrderFrequency saveOrderFrequency(OrderFrequency orderFrequency) throws APIException {
888
                return dao.saveOrderFrequency(orderFrequency);
1✔
889
        }
890
        
891
        /**
892
         * @see org.openmrs.api.OrderService#retireOrderFrequency(org.openmrs.OrderFrequency,
893
         *      java.lang.String)
894
         */
895
        @Override
896
        public OrderFrequency retireOrderFrequency(OrderFrequency orderFrequency, String reason) {
897
                return dao.saveOrderFrequency(orderFrequency);
1✔
898
        }
899
        
900
        /**
901
         * @see org.openmrs.api.OrderService#unretireOrderFrequency(org.openmrs.OrderFrequency)
902
         */
903
        @Override
904
        public OrderFrequency unretireOrderFrequency(OrderFrequency orderFrequency) {
905
                return Context.getOrderService().saveOrderFrequency(orderFrequency);
1✔
906
        }
907
        
908
        /**
909
         * @see org.openmrs.api.OrderService#purgeOrderFrequency(org.openmrs.OrderFrequency)
910
         */
911
        @Override
912
        public void purgeOrderFrequency(OrderFrequency orderFrequency) {
913
                
914
                if (dao.isOrderFrequencyInUse(orderFrequency)) {
1✔
915
                        throw new CannotDeleteObjectInUseException("Order.frequency.cannot.delete", (Object[]) null);
1✔
916
                }
917
                
918
                dao.purgeOrderFrequency(orderFrequency);
1✔
919
        }
1✔
920
        
921
        /**
922
         * @see org.openmrs.api.OrderService#getOrderFrequencyByConcept(org.openmrs.Concept)
923
         */
924
        @Override
925
        @Transactional(readOnly = true)
926
        public OrderFrequency getOrderFrequencyByConcept(Concept concept) {
927
                return dao.getOrderFrequencyByConcept(concept);
1✔
928
        }
929
        
930
        /**
931
         * @see GlobalPropertyListener#supportsPropertyName(String)
932
         */
933
        @Override
934
        public boolean supportsPropertyName(String propertyName) {
935
                return OpenmrsConstants.GP_ORDER_NUMBER_GENERATOR_BEAN_ID.equals(propertyName);
1✔
936
        }
937
        
938
        /**
939
         * @see GlobalPropertyListener#globalPropertyChanged(org.openmrs.GlobalProperty)
940
         */
941
        @Override
942
        public void globalPropertyChanged(GlobalProperty newValue) {
943
                setOrderNumberGenerator(null);
1✔
944
        }
1✔
945
        
946
        /**
947
         * @see GlobalPropertyListener#globalPropertyDeleted(String)
948
         */
949
        @Override
950
        public void globalPropertyDeleted(String propertyName) {
951
                setOrderNumberGenerator(null);
×
UNCOV
952
        }
×
953
        
954
        /**
955
         * Helper method to deter instance methods from setting static fields
956
         */
957
        private static void setOrderNumberGenerator(OrderNumberGenerator orderNumberGenerator) {
958
                OrderServiceImpl.orderNumberGenerator = orderNumberGenerator;
1✔
959
        }
1✔
960
        
961
        /**
962
         * @see org.openmrs.api.OrderService#getOrderType(Integer)
963
         */
964
        
965
        @Override
966
        @Transactional(readOnly = true)
967
        public OrderType getOrderType(Integer orderTypeId) {
968
                return dao.getOrderType(orderTypeId);
1✔
969
        }
970
        
971
        /**
972
         * @see org.openmrs.api.OrderService#getOrderTypeByUuid(String)
973
         */
974
        @Override
975
        @Transactional(readOnly = true)
976
        public OrderType getOrderTypeByUuid(String uuid) {
977
                return dao.getOrderTypeByUuid(uuid);
1✔
978
        }
979
        
980
        /**
981
         * @see org.openmrs.api.OrderService#getOrderTypes(boolean)
982
         */
983
        @Override
984
        @Transactional(readOnly = true)
985
        public List<OrderType> getOrderTypes(boolean includeRetired) {
986
                return dao.getOrderTypes(includeRetired);
1✔
987
        }
988
        
989
        /**
990
         * @see org.openmrs.api.OrderService#saveOrderType(org.openmrs.OrderType)
991
         */
992
        @Override
993
        public OrderType saveOrderType(OrderType orderType) {
994
                return dao.saveOrderType(orderType);
1✔
995
        }
996
        
997
        /**
998
         * @see org.openmrs.api.OrderService#purgeOrderType(org.openmrs.OrderType)
999
         */
1000
        @Override
1001
        public void purgeOrderType(OrderType orderType) {
1002
                if (dao.isOrderTypeInUse(orderType)) {
1✔
1003
                        throw new CannotDeleteObjectInUseException("Order.type.cannot.delete", (Object[]) null);
1✔
1004
                }
1005
                dao.purgeOrderType(orderType);
1✔
1006
        }
1✔
1007
        
1008
        /**
1009
         * @see org.openmrs.api.OrderService#retireOrderType(org.openmrs.OrderType, String)
1010
         */
1011
        @Override
1012
        public OrderType retireOrderType(OrderType orderType, String reason) {
1013
                return saveOrderType(orderType);
1✔
1014
        }
1015
        
1016
        /**
1017
         * @see org.openmrs.api.OrderService#unretireOrderType(org.openmrs.OrderType)
1018
         */
1019
        @Override
1020
        public OrderType unretireOrderType(OrderType orderType) {
1021
                return saveOrderType(orderType);
1✔
1022
        }
1023
        
1024
        /**
1025
         * @see org.openmrs.api.OrderService#getSubtypes(org.openmrs.OrderType, boolean)
1026
         */
1027
        @Override
1028
        @Transactional(readOnly = true)
1029
        public List<OrderType> getSubtypes(OrderType orderType, boolean includeRetired) {
1030
                List<OrderType> allSubtypes = new ArrayList<>();
1✔
1031
                List<OrderType> immediateAncestors = dao.getOrderSubtypes(orderType, includeRetired);
1✔
1032
                while (!immediateAncestors.isEmpty()) {
1✔
1033
                        List<OrderType> ancestorsAtNextLevel = new ArrayList<>();
1✔
1034
                        for (OrderType type : immediateAncestors) {
1✔
1035
                                allSubtypes.add(type);
1✔
1036
                                ancestorsAtNextLevel.addAll(dao.getOrderSubtypes(type, includeRetired));
1✔
1037
                        }
1✔
1038
                        immediateAncestors = ancestorsAtNextLevel;
1✔
1039
                }
1✔
1040
                return allSubtypes;
1✔
1041
        }
1042
        
1043
        /**
1044
         * @see org.openmrs.api.OrderService#getOrderTypeByConceptClass(org.openmrs.ConceptClass)
1045
         */
1046
        @Override
1047
        @Transactional(readOnly = true)
1048
        public OrderType getOrderTypeByConceptClass(ConceptClass conceptClass) {
1049
                return dao.getOrderTypeByConceptClass(conceptClass);
1✔
1050
        }
1051
        
1052
        /**
1053
         * @see org.openmrs.api.OrderService#getOrderTypeByConcept(org.openmrs.Concept)
1054
         */
1055
        @Override
1056
        @Transactional(readOnly = true)
1057
        public OrderType getOrderTypeByConcept(Concept concept) {
1058
                return Context.getOrderService().getOrderTypeByConceptClass(concept.getConceptClass());
1✔
1059
        }
1060
        
1061
        /**
1062
         * @see org.openmrs.api.OrderService#getDrugRoutes()
1063
         */
1064
        @Override
1065
        @Transactional(readOnly = true)
1066
        public List<Concept> getDrugRoutes() {
1067
                return getSetMembersOfConceptSetFromGP(OpenmrsConstants.GP_DRUG_ROUTES_CONCEPT_UUID);
1✔
1068
        }
1069
        
1070
        @Override
1071
        @Transactional(readOnly = true)
1072
        public List<Concept> getDrugDosingUnits() {
1073
                return getSetMembersOfConceptSetFromGP(OpenmrsConstants.GP_DRUG_DOSING_UNITS_CONCEPT_UUID);
1✔
1074
        }
1075
        
1076
        @Override
1077
        @Transactional(readOnly = true)
1078
        public List<Concept> getDrugDispensingUnits() {
1079
                List<Concept> dispensingUnits = new ArrayList<>(
1✔
1080
                                getSetMembersOfConceptSetFromGP(OpenmrsConstants.GP_DRUG_DISPENSING_UNITS_CONCEPT_UUID));
1✔
1081
                for (Concept concept : getDrugDosingUnits()) {
1✔
1082
                        if (!dispensingUnits.contains(concept)) {
1✔
1083
                                dispensingUnits.add(concept);
1✔
1084
                        }
1085
                }
1✔
1086
                return dispensingUnits;
1✔
1087
        }
1088
        
1089
        @Override
1090
        @Transactional(readOnly = true)
1091
        public List<Concept> getDurationUnits() {
1092
                return getSetMembersOfConceptSetFromGP(OpenmrsConstants.GP_DURATION_UNITS_CONCEPT_UUID);
1✔
1093
        }
1094
        
1095
        /**
1096
         * @see org.openmrs.api.OrderService#getTestSpecimenSources()
1097
         */
1098
        @Override
1099
        public List<Concept> getTestSpecimenSources() {
1100
                return getSetMembersOfConceptSetFromGP(OpenmrsConstants.GP_TEST_SPECIMEN_SOURCES_CONCEPT_UUID);
1✔
1101
        }
1102
        
1103
        @Override
1104
        public Concept getNonCodedDrugConcept() {
1105
                String conceptUuid = Context.getAdministrationService().getGlobalProperty(OpenmrsConstants.GP_DRUG_ORDER_DRUG_OTHER);
1✔
1106
                if (StringUtils.hasText(conceptUuid)) {
1✔
1107
                        return Context.getConceptService().getConceptByUuid(conceptUuid);
1✔
1108
                }
1109
                return null;
1✔
1110
        }
1111
        
1112
        @Override
1113
        @Transactional(readOnly = true)
1114
        public OrderGroup getOrderGroupByUuid(String uuid) throws APIException {
1115
                return dao.getOrderGroupByUuid(uuid);
1✔
1116
        }
1117
        
1118
        @Override
1119
        @Transactional(readOnly = true)
1120
        public OrderGroup getOrderGroup(Integer orderGroupId) throws APIException {
1121
                return dao.getOrderGroupById(orderGroupId);
1✔
1122
        }
1123
        
1124
        private List<Concept> getSetMembersOfConceptSetFromGP(String globalProperty) {
1125
                String conceptUuid = Context.getAdministrationService().getGlobalProperty(globalProperty);
1✔
1126
                Concept concept = Context.getConceptService().getConceptByUuid(conceptUuid);
1✔
1127
                if (concept != null && concept.getSet()) {
1✔
1128
                        return concept.getSetMembers();
1✔
1129
                }
1130
                return Collections.emptyList();
1✔
1131
        }
1132
        @Override
1133
        public List<OrderGroup> getOrderGroupsByPatient(Patient patient) throws APIException {
1134
                return dao.getOrderGroupsByPatient(patient);
1✔
1135
        }
1136

1137
        @Override
1138
        public List<OrderGroup> getOrderGroupsByEncounter(Encounter encounter) throws APIException {
1139
                return dao.getOrderGroupsByEncounter(encounter);
1✔
1140
        }
1141
        
1142
        /**
1143
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeTypes()
1144
         */
1145
        @Override
1146
        @Transactional(readOnly = true)
1147
        public List<OrderGroupAttributeType> getAllOrderGroupAttributeTypes() throws APIException {
1148
                return dao.getAllOrderGroupAttributeTypes();
1✔
1149
        }
1150
        
1151
        /**
1152
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeTypeById()
1153
         */
1154
        @Override
1155
        @Transactional(readOnly = true)
1156
        public OrderGroupAttributeType getOrderGroupAttributeType(Integer id) throws APIException {
1157
                return dao.getOrderGroupAttributeType(id);
1✔
1158
        }
1159
        
1160
        /**
1161
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeTypeByUuid()
1162
         */
1163
        @Override
1164
        @Transactional(readOnly = true)
1165
        public OrderGroupAttributeType getOrderGroupAttributeTypeByUuid(String uuid)throws APIException {
1166
                return dao.getOrderGroupAttributeTypeByUuid(uuid);
1✔
1167
        }
1168
        
1169
        /**
1170
         * @see org.openmrs.api.OrderService#saveOrderGroupAttributeType()
1171
         */
1172
        @Override
1173
        public OrderGroupAttributeType saveOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType) throws APIException{
1174
                return dao.saveOrderGroupAttributeType(orderGroupAttributeType);
1✔
1175
        }
1176

1177
        /**
1178
         * @see org.openmrs.api.OrderService#retireOrderGroupAttributeType()
1179
         */
1180
        @Override
1181
        public OrderGroupAttributeType retireOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType, String reason)throws APIException {
1182
                return Context.getOrderService().saveOrderGroupAttributeType(orderGroupAttributeType);
1✔
1183
        }
1184

1185
        /**
1186
         * @see org.openmrs.api.OrderService#unretireOrderGroupAttributeType()
1187
         */
1188
        @Override
1189
        public OrderGroupAttributeType unretireOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType)throws APIException {
1190
                return Context.getOrderService().saveOrderGroupAttributeType(orderGroupAttributeType);
1✔
1191
        }
1192

1193
        /**
1194
         * @see org.openmrs.api.OrderService#purgeOrderGroupAttributeType()
1195
         */
1196
        @Override
1197
        public void purgeOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType) throws APIException{
1198
                dao.deleteOrderGroupAttributeType(orderGroupAttributeType);
1✔
1199
        }
1✔
1200

1201
        /**
1202
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeTypeByName()
1203
         */
1204
        @Override
1205
        @Transactional(readOnly = true)
1206
        public OrderGroupAttributeType getOrderGroupAttributeTypeByName(String orderGroupAttributeTypeName)throws APIException {
1207
                return dao.getOrderGroupAttributeTypeByName(orderGroupAttributeTypeName);
1✔
1208
        }
1209

1210
        /**
1211
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeByUuid()
1212
         */
1213
        @Override
1214
        @Transactional(readOnly = true)
1215
        public OrderGroupAttribute getOrderGroupAttributeByUuid(String uuid)throws APIException {
1216
                return dao.getOrderGroupAttributeByUuid(uuid);
1✔
1217
        }
1218

1219
        /**
1220
         * @see org.openmrs.api.OrderService#getAllOrderAttributeTypes()
1221
         */
1222
        @Override
1223
        @Transactional(readOnly = true)
1224
        public List<OrderAttributeType> getAllOrderAttributeTypes() throws APIException {
1225
                return dao.getAllOrderAttributeTypes();
1✔
1226
        }
1227

1228
        /**
1229
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeById(Integer)
1230
         */
1231
        @Override
1232
        @Transactional(readOnly = true)
1233
        public OrderAttributeType getOrderAttributeTypeById(Integer id) throws APIException {
1234
                return dao.getOrderAttributeTypeById(id);
1✔
1235
        }
1236

1237
        /**
1238
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeByUuid(String)
1239
         */
1240
        @Override
1241
        @Transactional(readOnly = true)
1242
        public OrderAttributeType getOrderAttributeTypeByUuid(String uuid)throws APIException {
1243
                return dao.getOrderAttributeTypeByUuid(uuid);
1✔
1244
        }
1245

1246
        /**
1247
         * @see org.openmrs.api.OrderService#saveOrderAttributeType(OrderAttributeType)
1248
         */
1249
        @Override
1250
        public OrderAttributeType saveOrderAttributeType(OrderAttributeType orderAttributeType) throws APIException{
1251
                return dao.saveOrderAttributeType(orderAttributeType);
1✔
1252
        }
1253

1254
        /**
1255
         * @see org.openmrs.api.OrderService#retireOrderAttributeType(OrderAttributeType)
1256
         */
1257
        @Override
1258
        public OrderAttributeType retireOrderAttributeType(OrderAttributeType orderAttributeType, String reason)throws APIException {
1259
                return Context.getOrderService().saveOrderAttributeType(orderAttributeType);
1✔
1260
        }
1261

1262
        /**
1263
         * @see org.openmrs.api.OrderService#unretireOrderAttributeType(OrderAttributeType)
1264
         */
1265
        @Override
1266
        public OrderAttributeType unretireOrderAttributeType(OrderAttributeType orderAttributeType)throws APIException {
1267
                return Context.getOrderService().saveOrderAttributeType(orderAttributeType);
1✔
1268
        }
1269

1270
        /**
1271
         * @see org.openmrs.api.OrderService#purgeOrderAttributeType(OrderAttributeType)
1272
         */
1273
        @Override
1274
        public void purgeOrderAttributeType(OrderAttributeType orderAttributeType) throws APIException{
1275
                dao.deleteOrderAttributeType(orderAttributeType);
1✔
1276
        }
1✔
1277

1278
        /**
1279
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeByName(String)
1280
         */
1281
        @Override
1282
        @Transactional(readOnly = true)
1283
        public OrderAttributeType getOrderAttributeTypeByName(String orderAttributeTypeName)throws APIException {
1284
                return dao.getOrderAttributeTypeByName(orderAttributeTypeName);
1✔
1285
        }
1286

1287
        /**
1288
         * @see org.openmrs.api.OrderService#getOrderAttributeByUuid(String)
1289
         */
1290
        @Override
1291
        @Transactional(readOnly = true)
1292
        public OrderAttribute getOrderAttributeByUuid(String uuid)throws APIException {
1293
                return dao.getOrderAttributeByUuid(uuid);
1✔
1294
        }
1295
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc