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

openmrs / openmrs-core / 18843809507

27 Oct 2025 02:06PM UTC coverage: 65.295% (+0.007%) from 65.288%
18843809507

push

github

web-flow
TRUNK-6448: Orders: Allow setting Order Number and Stopping Inactive Orders Based On Global Property (#5418) (#5433)

17 of 23 new or added lines in 4 files covered. (73.91%)

1 existing line in 1 file now uncovered.

23719 of 36326 relevant lines covered (65.29%)

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.REVISE;
74

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1286
        /**
1287
         * @see org.openmrs.api.OrderService#getOrderAttributeByUuid(String)
1288
         */
1289
        @Override
1290
        @Transactional(readOnly = true)
1291
        public OrderAttribute getOrderAttributeByUuid(String uuid)throws APIException {
1292
                return dao.getOrderAttributeByUuid(uuid);
1✔
1293
        }
1294
}
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