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

openmrs / openmrs-core / 18842842547

27 Oct 2025 01:35PM UTC coverage: 64.894% (+0.008%) from 64.886%
18842842547

push

github

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

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

1 existing line in 1 file now uncovered.

23435 of 36113 relevant lines covered (64.89%)

0.65 hits per line

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

94.22
/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;
×
235
                        if (drugOrder.getDrug() != null) {
×
236
                                concept = drugOrder.getDrug().getConcept();
×
237
                                drugOrder.setConcept(concept);
×
238
                        }
239
                }
240
                if (concept == null) {
1✔
241
                        throw new MissingRequiredPropertyException("Order.concept.required");
×
242
                }
243
        }
1✔
244

245
        private void ensureDrugOrderAutoExpirationDateIsSet(Order order) {
246
                if (isDrugOrder(order)) {
1✔
247
                        ((DrugOrder) order).setAutoExpireDateBasedOnDuration();
1✔
248
                }
249
        }
1✔
250

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

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

296
        private void failOnOrderTypeMismatch(Order order) {
297
                if (!order.getOrderType().getJavaClass().isAssignableFrom(order.getClass())) {
1✔
298
                        throw new OrderEntryException("Order.type.class.does.not.match", new Object[] {
×
299
                                        order.getOrderType().getJavaClass(), order.getClass().getName() });
×
300
                }
301
        }
1✔
302

303
        private boolean areDrugOrdersOfSameOrderableAndOverlappingSchedule(Order firstOrder, Order secondOrder) {
304
                return firstOrder.hasSameOrderableAs(secondOrder)
1✔
305
                        && !OpenmrsUtil.nullSafeEquals(firstOrder.getPreviousOrder(), secondOrder)
1✔
306
                        && OrderUtil.checkScheduleOverlap(firstOrder, secondOrder)
1✔
307
                        && firstOrder.getOrderType().equals(
1✔
308
                            Context.getOrderService().getOrderTypeByUuid(OrderType.DRUG_ORDER_TYPE_UUID));
1✔
309
        }
310

311
        private boolean isDrugOrder(Order order) {
312
                return DrugOrder.class.isAssignableFrom(getActualType(order));
1✔
313
        }
314

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

533
        @Override
534
        public Order updateOrderFulfillerStatus(Order order, FulfillerStatus orderFulfillerStatus, String fullFillerComment,
535
                                                                                        String accessionNumber) {
536

537
                if (orderFulfillerStatus != null) {
1✔
538
                        order.setFulfillerStatus(orderFulfillerStatus);
1✔
539
                }
540

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

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

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

1171
        /**
1172
         * @see org.openmrs.api.OrderService#retireOrderGroupAttributeType()
1173
         */
1174
        @Override
1175
        public OrderGroupAttributeType retireOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType, String reason)throws APIException {
1176
                return Context.getOrderService().saveOrderGroupAttributeType(orderGroupAttributeType);
1✔
1177
        }
1178

1179
        /**
1180
         * @see org.openmrs.api.OrderService#unretireOrderGroupAttributeType()
1181
         */
1182
        @Override
1183
        public OrderGroupAttributeType unretireOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType)throws APIException {
1184
                return Context.getOrderService().saveOrderGroupAttributeType(orderGroupAttributeType);
1✔
1185
        }
1186

1187
        /**
1188
         * @see org.openmrs.api.OrderService#purgeOrderGroupAttributeType()
1189
         */
1190
        @Override
1191
        public void purgeOrderGroupAttributeType(OrderGroupAttributeType orderGroupAttributeType) throws APIException{
1192
                dao.deleteOrderGroupAttributeType(orderGroupAttributeType);
1✔
1193
        }
1✔
1194

1195
        /**
1196
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeTypeByName()
1197
         */
1198
        @Override
1199
        @Transactional(readOnly = true)
1200
        public OrderGroupAttributeType getOrderGroupAttributeTypeByName(String orderGroupAttributeTypeName)throws APIException {
1201
                return dao.getOrderGroupAttributeTypeByName(orderGroupAttributeTypeName);
1✔
1202
        }
1203

1204
        /**
1205
         * @see org.openmrs.api.OrderService#getOrderGroupAttributeByUuid()
1206
         */
1207
        @Override
1208
        @Transactional(readOnly = true)
1209
        public OrderGroupAttribute getOrderGroupAttributeByUuid(String uuid)throws APIException {
1210
                return dao.getOrderGroupAttributeByUuid(uuid);
1✔
1211
        }
1212

1213
        /**
1214
         * @see org.openmrs.api.OrderService#getAllOrderAttributeTypes()
1215
         */
1216
        @Override
1217
        @Transactional(readOnly = true)
1218
        public List<OrderAttributeType> getAllOrderAttributeTypes() throws APIException {
1219
                return dao.getAllOrderAttributeTypes();
1✔
1220
        }
1221

1222
        /**
1223
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeById(Integer)
1224
         */
1225
        @Override
1226
        @Transactional(readOnly = true)
1227
        public OrderAttributeType getOrderAttributeTypeById(Integer id) throws APIException {
1228
                return dao.getOrderAttributeTypeById(id);
1✔
1229
        }
1230

1231
        /**
1232
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeByUuid(String)
1233
         */
1234
        @Override
1235
        @Transactional(readOnly = true)
1236
        public OrderAttributeType getOrderAttributeTypeByUuid(String uuid)throws APIException {
1237
                return dao.getOrderAttributeTypeByUuid(uuid);
1✔
1238
        }
1239

1240
        /**
1241
         * @see org.openmrs.api.OrderService#saveOrderAttributeType(OrderAttributeType)
1242
         */
1243
        @Override
1244
        public OrderAttributeType saveOrderAttributeType(OrderAttributeType orderAttributeType) throws APIException{
1245
                return dao.saveOrderAttributeType(orderAttributeType);
1✔
1246
        }
1247

1248
        /**
1249
         * @see org.openmrs.api.OrderService#retireOrderAttributeType(OrderAttributeType)
1250
         */
1251
        @Override
1252
        public OrderAttributeType retireOrderAttributeType(OrderAttributeType orderAttributeType, String reason)throws APIException {
1253
                return Context.getOrderService().saveOrderAttributeType(orderAttributeType);
1✔
1254
        }
1255

1256
        /**
1257
         * @see org.openmrs.api.OrderService#unretireOrderAttributeType(OrderAttributeType)
1258
         */
1259
        @Override
1260
        public OrderAttributeType unretireOrderAttributeType(OrderAttributeType orderAttributeType)throws APIException {
1261
                return Context.getOrderService().saveOrderAttributeType(orderAttributeType);
1✔
1262
        }
1263

1264
        /**
1265
         * @see org.openmrs.api.OrderService#purgeOrderAttributeType(OrderAttributeType)
1266
         */
1267
        @Override
1268
        public void purgeOrderAttributeType(OrderAttributeType orderAttributeType) throws APIException{
1269
                dao.deleteOrderAttributeType(orderAttributeType);
1✔
1270
        }
1✔
1271

1272
        /**
1273
         * @see org.openmrs.api.OrderService#getOrderAttributeTypeByName(String)
1274
         */
1275
        @Override
1276
        @Transactional(readOnly = true)
1277
        public OrderAttributeType getOrderAttributeTypeByName(String orderAttributeTypeName)throws APIException {
1278
                return dao.getOrderAttributeTypeByName(orderAttributeTypeName);
1✔
1279
        }
1280

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