示例#1
0
		protected override void LinkProcedure(Procedure procedure)
		{
			if(this.Report == null)
				throw new WorkflowException("This step must be associated with a Report before procedures can be linked.");

			this.Report.LinkProcedure(procedure);
		}
示例#2
0
        public ReportSummary CreateReportSummary(Procedure rp, Report report, IPersistenceContext context)
        {
            ReportSummary summary = new ReportSummary();

            ProcedureAssembler rpAssembler = new ProcedureAssembler();
            if (report != null)
            {
                summary.ReportRef = report.GetRef();
                summary.ReportStatus = EnumUtils.GetEnumValueInfo(report.Status, context);

                // use all procedures attached to report
                summary.Procedures = CollectionUtils.Map<Procedure, ProcedureSummary>(report.Procedures,
                    delegate(Procedure p) { return rpAssembler.CreateProcedureSummary(p, context); });
            }
            else
            {
                // use supplied procedure
                summary.Procedures = CollectionUtils.Map<Procedure, ProcedureSummary>(new Procedure[] { rp },
                    delegate(Procedure p) { return rpAssembler.CreateProcedureSummary(p, context); });
            }

            Order order = rp.Order;

            summary.VisitNumber = new VisitAssembler().CreateVisitNumberDetail(order.Visit.VisitNumber);
            summary.AccessionNumber = order.AccessionNumber;
            summary.DiagnosticServiceName = order.DiagnosticService.Name;

            return summary;
        }
示例#3
0
文件: OrderRules.cs 项目: nhannd/Xian
		internal static TestResult PerformingDepartmentAlignsWithPerformingFacility(Procedure procedure)
		{
			// performing department must be associated with performing facility
			var performingDepartmentIsInPerformingFacility = procedure.PerformingDepartment == null
				|| procedure.PerformingFacility.Equals(procedure.PerformingDepartment.Facility);
			return new TestResult(performingDepartmentIsInPerformingFacility, SR.MessageValidateProcedurePerformingFacilityAndDepartment);
		}
示例#4
0
文件: OrderRules.cs 项目: nhannd/Xian
		internal static TestResult ModalitiesAlignWithPerformingFacility(Procedure procedure)
		{
			// modality facilities must match performing facility
			var valid = procedure.ModalityProcedureSteps.All(
				mps => ModalityAlignsWithPerformingFacility(mps).Success);

			return new TestResult(valid, SR.MessageValidateProcedurePerformingFacilityAndModalities);
		}
示例#5
0
		/// <summary>
		/// Creates a new work item.
		/// </summary>
		/// <param name="p"></param>
		/// <param name="expirationTime"></param>
		/// <returns></returns>
		public static WorkQueueItem CreateWorkQueueItem(Procedure p, TimeSpan expirationTime)
		{
			WorkQueueItem item = new WorkQueueItem(WorkQueueItemType);
			item.ExpirationTime = Platform.Time.Add(expirationTime);
			item.ExtendedProperties.Add(ProcedureOIDKey, p.GetRef().Serialize());

			return item;
		}
        public override ProcedureStep CreateInstance(XmlElement xmlNode, Procedure procedure)
        {
            Protocol protocol = new Protocol(procedure);
            ProtocolAssignmentStep step = new ProtocolAssignmentStep(protocol);

            //note: this is not ideal but there is no other way to save the protocol object
            PersistenceScope.CurrentContext.Lock(protocol, DirtyState.New);

            return step;
        }
示例#7
0
		public OrderListItem CreateOrderListItem(Procedure rp, IPersistenceContext context)
		{
			var data = new OrderListItem();

			UpdateListItem(data, rp.Order, context);
			UpdateListItem(data, rp.Order.Visit, context);
			UpdateListItem(data, rp, context);

			return data;
		}
示例#8
0
		public ReportListItem CreateReportListItem(Report report, Procedure rp, IPersistenceContext context)
		{
			var data = new ReportListItem();

			UpdateListItem(data, rp.Order, context);
			UpdateListItem(data, rp.Order.Visit, context);
			UpdateListItem(data, rp, context);
			UpdateListItem(data, report, context);

			return data;
		}
示例#9
0
文件: Report.cs 项目: nhannd/Xian
        /// <summary>
        /// Constructor for creating a new radiology report for the specified procedure.
        /// </summary>
        /// <param name="procedure">The procedure being reported.</param>
        public Report(Procedure procedure)
        {
            _procedures = new HashedSet<Procedure>();
            _parts = new List<ReportPart>();

            _procedures.Add(procedure);
            procedure.Reports.Add(this);

            // create the main report part
            ReportPart mainReport = new ReportPart(this, 0);
            _parts.Add(mainReport);
        }
示例#10
0
			public void EnqueueEvents(Procedure procedure)
			{
				var order = procedure.Order;

				var queueItem = new WorkQueueItem(WorkQueueItemType);
				queueItem.ExtendedProperties.Add("EventType", this.EventType);
				queueItem.ExtendedProperties.Add("OrderOID", order.OID.ToString());
				queueItem.ExtendedProperties.Add("AccessionNumber", order.AccessionNumber);
				queueItem.ExtendedProperties.Add("ProcedureOID", procedure.OID.ToString());
				queueItem.ExtendedProperties.Add("ProcedureNumber", procedure.Number);
				
				EnqueueWorkItem(queueItem);
			}
		public Healthcare.ImageAvailability ComputeProcedureImageAvailability(Procedure procedure, IPersistenceContext context)
		{
			// Find the number of instances recorded in the DicomSeries
			bool hasIncompleteDicomSeries;
			int numberOfInstancesFromDocumentation = QueryDocumentation(procedure.Order, out hasIncompleteDicomSeries);

			if (hasIncompleteDicomSeries)
			{
                return Healthcare.ImageAvailability.N;
			}
			else
			{
				bool studiesNotFound;
				int numberOfInstancesFromDicomServer;

                numberOfInstancesFromDicomServer = QueryDicomServer(procedure.Order,
                    _settings.DicomCallingAETitle,
                    _settings.DicomServerAETitle,
                    _settings.DicomServerHost,
                    _settings.DicomServerPort,
                    out studiesNotFound);

				// Compare recorded result with the result from Dicom Query 
				if (studiesNotFound || numberOfInstancesFromDicomServer == 0)
                {
                    return Healthcare.ImageAvailability.Z;
                }
                else if (numberOfInstancesFromDicomServer < numberOfInstancesFromDocumentation)
                {
                    return Healthcare.ImageAvailability.P;
                }
                else if (numberOfInstancesFromDicomServer == numberOfInstancesFromDocumentation)
                {
                    return Healthcare.ImageAvailability.C;
                }
                else if (numberOfInstancesFromDicomServer > numberOfInstancesFromDocumentation)
                {
                    // there are more images on the PACS than were recorded
                    // by the tech - perhaps documentation is incomplete
                    // consider this an 'indeterminate' scenario
                    return Healthcare.ImageAvailability.N;
                }
                else
                {
                    return Healthcare.ImageAvailability.N;
                }
			}
		}
示例#12
0
		public ProcedureSummary CreateProcedureSummary(Procedure rp, IPersistenceContext context)
		{
			var rptAssembler = new ProcedureTypeAssembler();
			var summary = new ProcedureSummary
							{
								OrderRef = rp.Order.GetRef(),
								ProcedureRef = rp.GetRef(),
								ScheduledStartTime = rp.ScheduledStartTime,
								SchedulingCode = EnumUtils.GetEnumValueInfo(rp.SchedulingCode),
								PerformingFacility = new FacilityAssembler().CreateFacilitySummary(rp.PerformingFacility),
								Type = rptAssembler.CreateSummary(rp.Type),
								Laterality = EnumUtils.GetEnumValueInfo(rp.Laterality, context),
								Portable = rp.Portable
							};

			return summary;
		}
示例#13
0
文件: Protocol.cs 项目: nhannd/Xian
		/// <summary>
		/// Links a <see cref="Procedure"/> to this report, meaning that the protocol covers
		/// this radiology procedure.
		/// </summary>
		/// <param name="procedure"></param>
		protected internal virtual void LinkProcedure(Procedure procedure)
		{
			if (_procedures.Contains(procedure))
				throw new WorkflowException("The procedure is already associated with this protocol.");

			// does the procedure already have a non-new protocol?
			Protocol otherProtocol = procedure.ActiveProtocol;
			if (otherProtocol.IsNew() == false && !this.Equals(otherProtocol))
				throw new WorkflowException("Cannot link this procedure because it already has an active protocol.");

			_procedures.Add(procedure);
			procedure.Protocols.Add(this);

            // dissociate the otherProtocol from the procedure
            // (ideally we should delete otherProtocol too, but how do we do that from here?)
            otherProtocol.Procedures.Remove(procedure);
        }
示例#14
0
		/// <summary>
		/// Creates procedure detail optionally including specified data.
		/// </summary>
		/// <param name="rp"></param>
		/// <param name="procedureStepFilter"></param>
		/// <param name="includeProtocol"></param>
		/// <param name="context"></param>
		/// <returns></returns>
		public ProcedureDetail CreateProcedureDetail(
			Procedure rp,
			Predicate<ProcedureStep> procedureStepFilter,
			bool includeProtocol,
			IPersistenceContext context)
		{
			var detail = new ProcedureDetail
							{
								ProcedureRef = rp.GetRef(),
								Status = EnumUtils.GetEnumValueInfo(rp.Status, context),
								Type = new ProcedureTypeAssembler().CreateSummary(rp.Type),
								ScheduledStartTime = rp.ScheduledStartTime,
								SchedulingCode = EnumUtils.GetEnumValueInfo(rp.SchedulingCode),
								StartTime = rp.StartTime,
								EndTime = rp.EndTime,
								CheckInTime = rp.ProcedureCheckIn.CheckInTime,
								CheckOutTime = rp.ProcedureCheckIn.CheckOutTime,
								PerformingFacility = new FacilityAssembler().CreateFacilitySummary(rp.PerformingFacility),
								PerformingDepartment = rp.PerformingDepartment == null ? null : new DepartmentAssembler().CreateSummary(rp.PerformingDepartment, context),
								Laterality = EnumUtils.GetEnumValueInfo(rp.Laterality, context),
								ImageAvailability = EnumUtils.GetEnumValueInfo(rp.ImageAvailability, context),
								Portable = rp.Portable,
								StudyInstanceUid = rp.StudyInstanceUID
							};

			var includedSteps = CollectionUtils.Select(rp.GetWorkflowHistory(), procedureStepFilter);
			if (includedSteps.Count > 0)
			{
				var procedureStepAssembler = new ProcedureStepAssembler();
				detail.ProcedureSteps = CollectionUtils.Map(
					includedSteps,
					(ProcedureStep ps) => procedureStepAssembler.CreateProcedureStepDetail(ps, context));
			}

			// the Protocol may be null, if this procedure has not been protocolled
			if (includeProtocol && rp.ActiveProtocol != null)
			{
				var protocolAssembler = new ProtocolAssembler();
				detail.Protocol = protocolAssembler.CreateProtocolDetail(rp.ActiveProtocol, context);
			}

			return detail;
		}
示例#15
0
        public override ProcedureStep CreateInstance(XmlElement xmlNode, Procedure procedure)
        {
            ModalityProcedureStep step = new ModalityProcedureStep();

            // set description
            step.Description = GetAttribute(xmlNode, "description", true);

            // set modality - need to look up by ID
            try
            {
                string modalityId = GetAttribute(xmlNode, "modality", true);
                ModalitySearchCriteria where = new ModalitySearchCriteria();
                where.Id.EqualTo(modalityId);

                // TODO might as well cache this query
                step.Modality = PersistenceScope.CurrentContext.GetBroker<IModalityBroker>().FindOne(where);
            }
            catch (EntityNotFoundException e)
            {
                throw new ProcedureBuilderException("Modality ID {0} is not valid.", e);
            }

            return step;
        }
 public DocumentationProcedureStep(Procedure procedure)
     : base(procedure)
 {
 }
 private void CheckStatus(ProcedureStatus status, Procedure o)
 {
     Assert.AreEqual(status, o.Status, string.Format("Exptected {0} status {1}", o.GetClass().Name, status.ToString()));
 }
示例#18
0
 public ReportingProcedureStep(Procedure procedure, ReportPart reportPart)
     : base(procedure)
 {
     _reportPart = reportPart;
 }
示例#19
0
文件: Report.cs 项目: nhannd/Xian
        /// <summary>
        /// Links a <see cref="Procedure"/> to this report, meaning that the report covers
        /// this radiology procedure.
        /// </summary>
        /// <param name="procedure"></param>
        protected internal virtual void LinkProcedure(Procedure procedure)
        {
            if (_procedures.Contains(procedure))
                throw new WorkflowException("The procedure is already associated with this report.");

            // does the procedure already have a report?
            Report otherReport = procedure.ActiveReport;
            if (otherReport != null && !this.Equals(otherReport))
                throw new WorkflowException("Cannot link this procedure because it already has an active report.");

            _procedures.Add(procedure);
            procedure.Reports.Add(this);
        }
示例#20
0
		private static void UpdateListItem(OrderListItem data, Procedure rp, IPersistenceContext context)
		{
			var rptAssembler = new ProcedureTypeAssembler();
			data.ProcedureRef = rp.GetRef();
			data.ProcedureType = rptAssembler.CreateSummary(rp.Type);
			data.ProcedureScheduledStartTime = rp.ScheduledStartTime;
			data.ProcedureSchedulingCode = EnumUtils.GetEnumValueInfo(rp.SchedulingCode);
			data.ProcedureCheckInTime = rp.ProcedureCheckIn.CheckInTime;
			data.ProcedureCheckOutTime = rp.ProcedureCheckIn.CheckOutTime;
			data.ProcedureStatus = EnumUtils.GetEnumValueInfo(rp.Status, context);
			data.ProcedurePerformingFacility = new FacilityAssembler().CreateFacilitySummary(rp.PerformingFacility);
			data.ProcedurePortable = rp.Portable;
			data.ProcedureLaterality = EnumUtils.GetEnumValueInfo(rp.Laterality, context);
		}
示例#21
0
		private void UpdateProceduresHelper(Order order, IEnumerable<ProcedureRequisition> procedureReqs, ModifyOrderRequest request)
		{
			// do not update the procedures if the order is completed
			if (order.IsTerminated)
				return;

			var assembler = new OrderEntryAssembler();

			// if any procedure is in downtime recovery mode, assume the entire order is a "downtime order"
			var isDowntime = CollectionUtils.Contains(order.Procedures, p => p.DowntimeRecoveryMode);

			// separate the list into additions and updates
			var existingReqs = new List<ProcedureRequisition>();
			var addedReqs = new List<ProcedureRequisition>();

			foreach (var req in procedureReqs)
			{
				if (CollectionUtils.Contains(order.Procedures, x => req.ProcedureNumber == x.Number))
				{
					existingReqs.Add(req);
				}
				else
				{
					addedReqs.Add(req);
				}
			}

			// process the additions first, so that we don't accidentally cancel an order (if all its procedures are cancelled momentarily)
			var procedureNumberBroker = PersistenceContext.GetBroker<IProcedureNumberBroker>();
			var dicomUidBroker = PersistenceContext.GetBroker<IDicomUidBroker>();
			foreach (var req in addedReqs)
			{
				var requestedType = this.PersistenceContext.Load<ProcedureType>(req.ProcedureType.ProcedureTypeRef);

				// create a new procedure for this requisition
				var procedure = new Procedure(requestedType, procedureNumberBroker.GetNext(), dicomUidBroker.GetNewUid()) { DowntimeRecoveryMode = isDowntime };
				order.AddProcedure(procedure);

				// note: need to lock the new procedure now, prior to creating the procedure steps
				// otherwise may get exceptions saying the Procedure is a transient object
				this.PersistenceContext.Lock(procedure, DirtyState.New);

				// create the procedure steps
				procedure.CreateProcedureSteps();

				// apply the requisition information to the actual procedure
				assembler.UpdateProcedureFromRequisition(procedure, req, this.CurrentUserStaff, this.PersistenceContext);

				LogicalHL7Event.ProcedureCreated.EnqueueEvents(procedure);
			}

			// process updates
			foreach (var req in existingReqs)
			{
				var requestedType = this.PersistenceContext.Load<ProcedureType>(req.ProcedureType.ProcedureTypeRef);
				var procedure = CollectionUtils.SelectFirst(order.Procedures, x => req.ProcedureNumber == x.Number);

				// validate that the type has not changed
				if (!procedure.Type.Equals(requestedType))
					throw new RequestValidationException("Order modification must not modify the type of a requested procedure.");

				// If the procedure is already terminated, just move on to the next one since procedures cannot be "un-terminated".
				if (procedure.IsTerminated)
					continue;

				// apply the requisition information to the actual procedure
				assembler.UpdateProcedureFromRequisition(procedure, req, this.CurrentUserStaff, this.PersistenceContext);

				(req.Cancelled ? LogicalHL7Event.ProcedureCancelled : LogicalHL7Event.ProcedureModified).EnqueueEvents(procedure);
			}
		}
示例#22
0
		public override ProcedureStep CreateInstance(XmlElement xmlNode, Procedure procedure)
		{
			return new RegistrationProcedureStep();
		}
示例#23
0
		/// <summary>
		/// Creates an instance of a procedure plan using the specified procedure as a prototype.
		/// </summary>
		/// <param name="procedure"></param>
		/// <returns></returns>
		public static ProcedurePlan CreateFromProcedure(Procedure procedure)
		{
			var builder = new ProcedureBuilder();
			var xmldoc = builder.CreatePlanFromProcedure(procedure);
			return new ProcedurePlan(xmldoc);
		}
		// arguably this is a business logic decision that shouldn't go here, but there is really no
		// better place to put it right now
		// note that the notion of "modifiable" here is specific to the idea of a "requisition"
		// The "requisition" is modifiable only as long as the procedure is in the SC status
		private static bool IsProcedureModifiable(Procedure procedure)
		{
			return procedure.Status == ProcedureStatus.SC;
		}
示例#25
0
 public DocumentationProcedureStep(Procedure procedure)
     : base(procedure)
 {
 }
		public void UpdateProcedureFromRequisition(Procedure procedure, ProcedureRequisition requisition, Staff currentUserStaff, IPersistenceContext context)
		{
			// check if the procedure was cancelled
			if (requisition.Cancelled)
			{
				if (procedure.Status == ProcedureStatus.SC)
				{
					// if RP is still scheduled, cancel it
					procedure.Cancel();
				}
				else if (procedure.Status == ProcedureStatus.IP)
				{
					// if RP in-progress, discontinue it
					procedure.Discontinue();
				}

				// early exit - nothing else to update
				return;
			}

			// The following properties are appropriate only for procedures in SC status.
			if (!IsProcedureModifiable(procedure))
				return;

			procedure.Schedule(requisition.ScheduledTime, requisition.ScheduledDuration);
			procedure.SchedulingCode = EnumUtils.GetEnumValue<SchedulingCodeEnum>(requisition.SchedulingCode, context);

			procedure.PerformingFacility = context.Load<Facility>(requisition.PerformingFacility.FacilityRef, EntityLoadFlags.Proxy);
			procedure.PerformingDepartment = requisition.PerformingDepartment == null ? null
				: context.Load<Department>(requisition.PerformingDepartment.DepartmentRef, EntityLoadFlags.Proxy);

			// if the requisition explicitly specifies a modality, assign that modality to all MPS
			// (we ignore the fact that the procedure plan can theoretically contain modality procedures steps spanning multiple 
			// DICOM modalities, since in the small clinic use-case, each procedure type generally only has a single MPS)
			if (requisition.Modality != null)
			{
				foreach (var mps in procedure.ModalityProcedureSteps)
				{
					mps.Modality = context.Load<Modality>(requisition.Modality.ModalityRef, EntityLoadFlags.Proxy);
				}
			}

			procedure.Laterality = EnumUtils.GetEnumValue<Laterality>(requisition.Laterality);
			procedure.Portable = requisition.PortableModality;

			if (requisition.CheckedIn && procedure.IsPreCheckIn)
			{
				procedure.CheckIn(currentUserStaff, null);
			}
			else if (!requisition.CheckedIn && procedure.IsCheckedIn)
			{
				procedure.RevertCheckIn();
			}
		}
		public ProcedureRequisition CreateProcedureRequisition(Procedure procedure, IPersistenceContext context)
		{
			var modality = procedure.ModalityProcedureSteps.Select(mps => mps.Modality).FirstOrDefault();

			var procedureTypeAssembler = new ProcedureTypeAssembler();
			var facilityAssembler = new FacilityAssembler();
			var departmentAssembler = new DepartmentAssembler();
			var modalityAssembler = new ModalityAssembler();

			// create requisition
			return new ProcedureRequisition(
				procedure.GetRef(),
				procedureTypeAssembler.CreateSummary(procedure.Type),
				procedure.Number,
				procedure.ScheduledStartTime,
				procedure.ScheduledDuration,
				modalityAssembler.CreateModalitySummary(modality),
				EnumUtils.GetEnumValueInfo(procedure.SchedulingCode),
				procedure.PerformingFacility == null ? null : facilityAssembler.CreateFacilitySummary(procedure.PerformingFacility),
				procedure.PerformingDepartment == null ? null : departmentAssembler.CreateSummary(procedure.PerformingDepartment, context),
				EnumUtils.GetEnumValueInfo(procedure.Laterality, context),
				procedure.Portable,
				procedure.IsPreCheckIn == false,
				EnumUtils.GetEnumValueInfo(procedure.Status, context),
				IsProcedureModifiable(procedure),
				procedure.Status == ProcedureStatus.CA || procedure.Status == ProcedureStatus.DC);
		}
示例#28
0
		private InterpretationStep GetPendingInterpretationStep(Procedure procedure)
		{
			// bug #3859: don't want to create an interpretation step for a completed procedure
			// (migrated data may not have any interpretation steps even for a completed procedure)
			if (procedure.IsTerminated)
				return null;

			var interpretationSteps = CollectionUtils.Select(
				procedure.ProcedureSteps,
				ps => ps.Is<InterpretationStep>());

			// no interp step, so create one
			if (interpretationSteps.Count == 0)
			{
				var interpretationStep = new InterpretationStep(procedure);
				this.PersistenceContext.Lock(interpretationStep, DirtyState.New);
				return interpretationStep;
			}

			// may be multiple interp steps (eg maybe one was started and discontinued), so find the one that is scheduled
			var pendingStep = CollectionUtils.SelectFirst(
				interpretationSteps,
				ps => ps.State == ActivityStatus.SC);

			return pendingStep == null ? null : pendingStep.As<InterpretationStep>();
		}
示例#29
0
		public Protocol(Procedure procedure)
			: this()
		{
			_procedures.Add(procedure);
			procedure.Protocols.Add(this);
		}
示例#30
0
		public RegistrationProcedureStep(Procedure procedure)
			: base(procedure)
		{
		}
 public ReportingProcedureStep(Procedure procedure, ReportPart reportPart)
     :base(procedure)
 {
     _reportPart = reportPart;
 }
示例#32
0
        /// <summary>
        /// Sets the plan for this procedure type from the specified prototype procedure.
        /// </summary>
        /// <param name="prototype"></param>
        public virtual void SetPlanFromPrototype(Procedure prototype)
        {
			this.Plan = ProcedurePlan.CreateFromProcedure(prototype);
        }