예제 #1
0
파일: Order.cs 프로젝트: hksonngan/Xian
        /// <summary>
        /// Cancels the order.
        /// </summary>
        /// <param name="cancelInfo"></param>
        public virtual void Cancel(OrderCancelInfo cancelInfo)
        {
            if (this.Status != OrderStatus.SC)
            {
                throw new WorkflowException("Only orders in the SC status can be canceled");
            }

            _cancelInfo = cancelInfo;

            // cancel/discontinue all procedures
            foreach (var procedure in _procedures)
            {
                // given that the order is still in SC, all procedures must be either
                // SC or CA - and only those in SC need to be cancelled
                if (procedure.Status == ProcedureStatus.SC)
                {
                    procedure.Cancel();
                }
            }

            // if the order was replaced, change the status to RP
            if (cancelInfo.ReplacementOrder != null)
            {
                SetStatus(OrderStatus.RP);
            }

            // need to update the end-time again, after cacnelling procedures
            UpdateEndTime();
        }
예제 #2
0
파일: Order.cs 프로젝트: hksonngan/Xian
        /// <summary>
        /// Discontinues the order.
        /// </summary>
        public virtual void Discontinue(OrderCancelInfo cancelInfo)
        {
            if (this.Status != OrderStatus.IP)
            {
                throw new WorkflowException("Only orders in the IP status can be discontinued");
            }

            _cancelInfo = cancelInfo;

            // update the status prior to cancelling the procedures
            // (otherwise cancelling the procedures will cause them to try and update the order status)
            SetStatus(OrderStatus.DC);

            // cancel or discontinue any non-terminated procedures
            foreach (var procedure in _procedures)
            {
                if (procedure.Status == ProcedureStatus.SC)
                {
                    procedure.Cancel();
                }
                else if (procedure.Status == ProcedureStatus.IP)
                {
                    procedure.Discontinue();
                }
            }

            // need to update the end-time again, after discontinuing procedures
            UpdateEndTime();
        }
예제 #3
0
파일: Order.cs 프로젝트: hksonngan/Xian
        /// <summary>
        /// Gets a value indicating whether this order can be unmerged from its merge destination.
        /// </summary>
        /// <param name="cancelInfo"></param>
        /// <param name="failureReason"></param>
        /// <returns></returns>
        public virtual bool CanUnmerge(OrderCancelInfo cancelInfo, out string failureReason)
        {
            var destOrder = _mergeInfo.MergeDestinationOrder;

            failureReason = null;
            if (_status != OrderStatus.MG || destOrder == null)
            {
                failureReason = "Only orders in the MG status can be unmerged.";
            }
            else if (destOrder.Status != OrderStatus.SC)
            {
                failureReason = "Cannot unmerge because the merge target order has already been started.";
            }
            else if (CollectionUtils.Contains(destOrder.Procedures, p => p.Status == ProcedureStatus.CA))
            {
                failureReason = "Cannot unmerge because the merge target order has cancelled procedures.";
            }
            else if (cancelInfo.Reason == null)
            {
                failureReason = "A reason must be provided to unmerge.";
            }
            else if (CollectionUtils.Contains(this.Procedures, p => p.DowntimeRecoveryMode) ||
                     CollectionUtils.Contains(destOrder.Procedures, p => p.DowntimeRecoveryMode))
            {
                failureReason = "Downtime orders cannot be unmerged.";
            }

            return(string.IsNullOrEmpty(failureReason));
        }
예제 #4
0
파일: Order.cs 프로젝트: bangush/server-1
        /// <summary>
        /// Gets a value indicating whether this order can be unmerged from its merge destination.
        /// </summary>
        /// <param name="cancelInfo"></param>
        /// <param name="failureReason"></param>
        /// <returns></returns>
        public virtual bool CanUnmerge(OrderCancelInfo cancelInfo, out string failureReason)
        {
            // Bug #12488 - unmerging orders as it exists currently will leave ghost procedures around, which can eventually corrupt the order state after repeated merge-unmerge cycles
            failureReason = "Not Supported";
            return(false);

            //var destOrder = _mergeInfo.MergeDestinationOrder;
            //failureReason = null;
            //if (_status != OrderStatus.MG || destOrder == null)
            //    failureReason = "Only orders in the MG status can be unmerged.";
            //else if (destOrder.Status != OrderStatus.SC)
            //    failureReason = "Cannot unmerge because the merge target order has already been started.";
            //else if(CollectionUtils.Contains(destOrder.Procedures, p => p.Status == ProcedureStatus.CA))
            //    failureReason = "Cannot unmerge because the merge target order has cancelled procedures.";
            //else if (cancelInfo.Reason == null)
            //    failureReason = "A reason must be provided to unmerge.";
            //else if (CollectionUtils.Contains(this.Procedures, p => p.DowntimeRecoveryMode)
            //    || CollectionUtils.Contains(destOrder.Procedures, p => p.DowntimeRecoveryMode))
            //    failureReason = "Downtime orders cannot be unmerged.";

            //return string.IsNullOrEmpty(failureReason);
        }
예제 #5
0
파일: Order.cs 프로젝트: hksonngan/Xian
        /// <summary>
        /// Un-merges this order from its merge destination, returning a new order with the specified accession #,
        /// and marking this order as Replaced by the new order.
        /// </summary>
        /// <param name="cancelInfo"></param>
        /// <param name="newAccessionNumber"></param>
        /// <returns></returns>
        public virtual UnmergeResult Unmerge(OrderCancelInfo cancelInfo, string newAccessionNumber)
        {
            string failureReason;

            if (!CanUnmerge(cancelInfo, out failureReason))
            {
                throw new WorkflowException(failureReason);
            }

            var destOrder = _mergeInfo.MergeDestinationOrder;


            // create replacement order
            var newOrder = new Order(
                _patient,
                _visit,
                null,                           // do not copy placer-number
                newAccessionNumber,             // assign new acc #
                _diagnosticService,
                _enteredTime,
                _enteredBy,
                _enteredComment,
                _schedulingRequestTime,
                null,                         // will be set by call to UpdateScheduling()
                null,
                null,
                _orderingPractitioner,
                _orderingFacility,
                new HashedSet <Procedure>(),                        // will be added later
                new HashedSet <Procedure>(),                        // ghosts
                CollectionUtils.Map(_resultRecipients, (ResultRecipient rr) => (ResultRecipient)rr.Clone()),
                new List <OrderAttachment>(),
                _reasonForStudy,
                _priority,
                (int)_priority,
                OrderStatus.SC,
                null,
                null,
                new HashedSet <Order>(),
                ExtendedPropertyUtils.Copy(_extendedProperties)
                );


            // reclaim order notes
            var notes        = OrderNote.GetNotesForOrder(this);
            var reclaimNotes = CollectionUtils.Map(
                CollectionUtils.Select(notes, n => n.GhostOf != null),
                (OrderNote n) => n.GhostOf.Downcast <OrderNote>());

            foreach (var note in reclaimNotes)
            {
                note.Order = newOrder;
            }

            // reclaim attachments
            var reclaimAttachments = CollectionUtils.Map(_attachments,
                                                         (OrderAttachment a) =>
                                                         CollectionUtils.SelectFirst(destOrder.Attachments, b => Equals(a.Document.GhostOf, b.Document)));

            foreach (var attachment in reclaimAttachments)
            {
                destOrder.Attachments.Remove(attachment);
                newOrder.Attachments.Add(attachment);
            }

            // reclaim procedures
            // need to create new ghost copies on the dest order, so that HL7 can cancel them
            var reclaimProcedures = CollectionUtils.Map(_ghostProcedures, (Procedure p) => p.GhostOf);
            var ghostProcedures   = CollectionUtils.Map(reclaimProcedures, (Procedure p) => p.CreateGhostCopy());

            foreach (var procedure in reclaimProcedures)
            {
                newOrder.AddProcedure(procedure);
            }
            destOrder.Procedures.AddAll(ghostProcedures);               // note: procedure Indexes are already set correctly

            // update scheduling/status information
            newOrder.UpdateScheduling();
            newOrder.UpdateStatus();

            // any orders that were merged into this order must be redirected to the new order,
            // in order to support recursive unmerge
            foreach (var sourceOrder in _mergeSourceOrders)
            {
                sourceOrder.MergeInfo.MergeDestinationOrder = newOrder;
                newOrder.MergeSourceOrders.Add(sourceOrder);
            }
            _mergeSourceOrders.Clear();

            // change status of this order to RP, and set cancel info
            _cancelInfo = (OrderCancelInfo)cancelInfo.Clone();
            _cancelInfo.ReplacementOrder = newOrder;

            // clear merge info on this order, since it is no longer considered merged
            _mergeInfo = null;

            // set status of this order to RP, and set end time manually
            SetStatus(OrderStatus.RP);
            _endTime = Platform.Time;

            return(new UnmergeResult {
                ReplacementOrder = newOrder, GhostProcedures = ghostProcedures
            });
        }
예제 #6
0
		private void UnmergeHelper(IEnumerable<Order> sourceOrders, OrderCancelInfo cancelInfo, IAccessionNumberBroker accBroker)
		{
			foreach (var order in sourceOrders)
			{
				string failureReason;
				if (!order.CanUnmerge(cancelInfo, out failureReason))
					throw new RequestValidationException(failureReason);

				var result = order.Unmerge(cancelInfo, accBroker.GetNext());
				var replacementOrder = result.ReplacementOrder;
				PersistenceContext.Lock(replacementOrder, DirtyState.New);

				// sync state so that ghost procedures get OIDs, prior to queuing ghost HL7 events
				PersistenceContext.SynchState();

				// notify HL7 of cancelled procedures (now existing as ghosts on dest order)
				foreach (var procedure in result.GhostProcedures)
				{
					LogicalHL7Event.ProcedureCancelled.EnqueueEvents(procedure);
				}

				// if the replacement order is not terminated
				if (!replacementOrder.IsTerminated)
				{
					// notify HL7 of replacement
					LogicalHL7Event.OrderCreated.EnqueueEvents(replacementOrder);

					// recur on items that were merged into this order
					UnmergeHelper(replacementOrder.MergeSourceOrders, cancelInfo, accBroker);
				}
			}
		}
예제 #7
0
		public UnmergeOrderResponse UnmergeOrder(UnmergeOrderRequest request)
		{
			Platform.CheckForNullReference(request, "request");
			Platform.CheckMemberIsSet(request.OrderRef, "OrderRef");

			// reason is not required for dry run, but otherwise it is
			if (!request.DryRun && request.UnmergeReason == null)
				throw new ArgumentNullException("UnmergeReason");

			DryRunHelper(request.DryRun,
				delegate
				{
					var destinationOrder = this.PersistenceContext.Load<Order>(request.OrderRef);
					var sourceOrders = destinationOrder.MergeSourceOrders;
					if (sourceOrders.Count == 0)
						throw new RequestValidationException("This order does not have any orders to un-merge.");

					// load the reason; if reason is null (eg dry run), just get the first available reason
					var reason = request.UnmergeReason == null ?
						CollectionUtils.FirstElement(PersistenceContext.GetBroker<IEnumBroker>().Load<OrderCancelReasonEnum>(false))
						: EnumUtils.GetEnumValue<OrderCancelReasonEnum>(request.UnmergeReason, PersistenceContext);

					var cancelInfo = new OrderCancelInfo(reason, this.CurrentUserStaff, "Un-merged");
					var accBroker = PersistenceContext.GetBroker<IAccessionNumberBroker>();

					// do unmerge
					UnmergeHelper(sourceOrders, cancelInfo, accBroker);
				});

			return new UnmergeOrderResponse();
		}
예제 #8
0
		private static void CancelOrderHelper(Order order, OrderCancelInfo info)
		{
			var operation = new CancelOrDiscontinueOrderOperation();
			operation.Execute(order, info);
		}
예제 #9
0
		/// <summary>
		/// Discontinues the order.
		/// </summary>
		public virtual void Discontinue(OrderCancelInfo cancelInfo)
		{
			if (this.Status != OrderStatus.IP)
				throw new WorkflowException("Only orders in the IP status can be discontinued");

			_cancelInfo = cancelInfo;

			// update the status prior to cancelling the procedures
			// (otherwise cancelling the procedures will cause them to try and update the order status)
			SetStatus(OrderStatus.DC);

			// cancel or discontinue any non-terminated procedures
			foreach (var procedure in _procedures)
			{
				if (procedure.Status == ProcedureStatus.SC)
					procedure.Cancel();
				else if (procedure.Status == ProcedureStatus.IP)
					procedure.Discontinue();
			}

			// need to update the end-time again, after discontinuing procedures
			UpdateEndTime();
		}
예제 #10
0
		/// <summary>
		/// Cancels the order.
		/// </summary>
		/// <param name="cancelInfo"></param>
		public virtual void Cancel(OrderCancelInfo cancelInfo)
		{
			if (this.Status != OrderStatus.SC)
				throw new WorkflowException("Only orders in the SC status can be canceled");

			_cancelInfo = cancelInfo;

			// cancel/discontinue all procedures
			foreach (var procedure in _procedures)
			{
				// given that the order is still in SC, all procedures must be either
				// SC or CA - and only those in SC need to be cancelled
				if (procedure.Status == ProcedureStatus.SC)
					procedure.Cancel();
			}

			// if the order was replaced, change the status to RP
			if (cancelInfo.ReplacementOrder != null)
				SetStatus(OrderStatus.RP);

			// need to update the end-time again, after cacnelling procedures
			UpdateEndTime();
		}
예제 #11
0
		/// <summary>
		/// Un-merges this order from its merge destination, returning a new order with the specified accession #,
		/// and marking this order as Replaced by the new order.
		/// </summary>
		/// <param name="cancelInfo"></param>
		/// <param name="newAccessionNumber"></param>
		/// <returns></returns>
		public virtual UnmergeResult Unmerge(OrderCancelInfo cancelInfo, string newAccessionNumber)
		{
			string failureReason;
			if (!CanUnmerge(cancelInfo, out failureReason))
				throw new WorkflowException(failureReason);

			var destOrder = _mergeInfo.MergeDestinationOrder;


			// create replacement order
			var newOrder = new Order(
					_patient,
					_visit,
					null,	// do not copy placer-number
					newAccessionNumber,  // assign new acc #
					_diagnosticService,
					_enteredTime,
					_enteredBy,
					_enteredComment,
					_schedulingRequestTime,
					null, // will be set by call to UpdateScheduling()
					null,
					null,
					_orderingPractitioner,
					_orderingFacility,
					new HashedSet<Procedure>(), // will be added later
					new HashedSet<Procedure>(), // ghosts
					CollectionUtils.Map(_resultRecipients, (ResultRecipient rr) => (ResultRecipient)rr.Clone()),
					new List<OrderAttachment>(),
					_reasonForStudy,
					_priority,
					(int)_priority,
					OrderStatus.SC,
					null,
					null,
					new HashedSet<Order>(),
					ExtendedPropertyUtils.Copy(_extendedProperties)
				);


			// reclaim order notes
			var notes = OrderNote.GetNotesForOrder(this);
			var reclaimNotes = CollectionUtils.Map(
				CollectionUtils.Select(notes, n => n.GhostOf != null),
				(OrderNote n) => n.GhostOf.Downcast<OrderNote>());
			foreach (var note in reclaimNotes)
			{
				note.Order = newOrder;
			}

			// reclaim attachments
			var reclaimAttachments = CollectionUtils.Map(_attachments,
				(OrderAttachment a) => 
					CollectionUtils.SelectFirst(destOrder.Attachments, b => Equals(a.Document.GhostOf, b.Document)));
			foreach (var attachment in reclaimAttachments)
			{
				destOrder.Attachments.Remove(attachment);
				newOrder.Attachments.Add(attachment);
			}

			// reclaim procedures
			// need to create new ghost copies on the dest order, so that HL7 can cancel them
			var reclaimProcedures = CollectionUtils.Map(_ghostProcedures, (Procedure p) => p.GhostOf);
			var ghostProcedures = CollectionUtils.Map(reclaimProcedures, (Procedure p) => p.CreateGhostCopy());
			foreach (var procedure in reclaimProcedures)
			{
				newOrder.AddProcedure(procedure);
			}
			destOrder.Procedures.AddAll(ghostProcedures);	// note: procedure Indexes are already set correctly

			// update scheduling/status information
			newOrder.UpdateScheduling();
			newOrder.UpdateStatus();

			// any orders that were merged into this order must be redirected to the new order,
			// in order to support recursive unmerge
			foreach (var sourceOrder in _mergeSourceOrders)
			{
				sourceOrder.MergeInfo.MergeDestinationOrder = newOrder;
				newOrder.MergeSourceOrders.Add(sourceOrder);
			}
			_mergeSourceOrders.Clear();

			// change status of this order to RP, and set cancel info
			_cancelInfo = (OrderCancelInfo)cancelInfo.Clone();
			_cancelInfo.ReplacementOrder = newOrder;

			// clear merge info on this order, since it is no longer considered merged
			_mergeInfo = null;

			// set status of this order to RP, and set end time manually
			SetStatus(OrderStatus.RP);
			_endTime = Platform.Time;

			return new UnmergeResult {ReplacementOrder = newOrder, GhostProcedures = ghostProcedures};
		}
예제 #12
0
		/// <summary>
		/// Gets a value indicating whether this order can be unmerged from its merge destination.
		/// </summary>
		/// <param name="cancelInfo"></param>
		/// <param name="failureReason"></param>
		/// <returns></returns>
		public virtual bool CanUnmerge(OrderCancelInfo cancelInfo, out string failureReason)
		{
			// Bug #12488 - unmerging orders as it exists currently will leave ghost procedures around, which can eventually corrupt the order state after repeated merge-unmerge cycles
			failureReason = "Not Supported";
			return false;

			//var destOrder = _mergeInfo.MergeDestinationOrder;
			//failureReason = null;
			//if (_status != OrderStatus.MG || destOrder == null)
			//    failureReason = "Only orders in the MG status can be unmerged.";
			//else if (destOrder.Status != OrderStatus.SC)
			//    failureReason = "Cannot unmerge because the merge target order has already been started.";
			//else if(CollectionUtils.Contains(destOrder.Procedures, p => p.Status == ProcedureStatus.CA))
			//    failureReason = "Cannot unmerge because the merge target order has cancelled procedures.";
			//else if (cancelInfo.Reason == null)
			//    failureReason = "A reason must be provided to unmerge.";
			//else if (CollectionUtils.Contains(this.Procedures, p => p.DowntimeRecoveryMode)
			//    || CollectionUtils.Contains(destOrder.Procedures, p => p.DowntimeRecoveryMode))
			//    failureReason = "Downtime orders cannot be unmerged.";

			//return string.IsNullOrEmpty(failureReason);
		}
예제 #13
0
파일: Order.cs 프로젝트: nhannd/Xian
		/// <summary>
		/// Gets a value indicating whether this order can be unmerged from its merge destination.
		/// </summary>
		/// <param name="cancelInfo"></param>
		/// <param name="failureReason"></param>
		/// <returns></returns>
		public virtual bool CanUnmerge(OrderCancelInfo cancelInfo, out string failureReason)
		{
			var destOrder = _mergeInfo.MergeDestinationOrder;
			failureReason = null;
			if (_status != OrderStatus.MG || destOrder == null)
				failureReason = "Only orders in the MG status can be unmerged.";
			else if (destOrder.Status != OrderStatus.SC)
				failureReason = "Cannot unmerge because the merge target order has already been started.";
			else if(CollectionUtils.Contains(destOrder.Procedures, p => p.Status == ProcedureStatus.CA))
				failureReason = "Cannot unmerge because the merge target order has cancelled procedures.";
			else if (cancelInfo.Reason == null)
				failureReason = "A reason must be provided to unmerge.";
			else if (CollectionUtils.Contains(this.Procedures, p => p.DowntimeRecoveryMode)
				|| CollectionUtils.Contains(destOrder.Procedures, p => p.DowntimeRecoveryMode))
				failureReason = "Downtime orders cannot be unmerged.";

			return string.IsNullOrEmpty(failureReason);
		}