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); }
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; }
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); }
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); }
/// <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; }
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; }
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; }
/// <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); }
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; } } }
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; }
/// <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); }
/// <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; }
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())); }
public ReportingProcedureStep(Procedure procedure, ReportPart reportPart) : base(procedure) { _reportPart = reportPart; }
/// <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); }
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); }
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); } }
public override ProcedureStep CreateInstance(XmlElement xmlNode, Procedure procedure) { return new RegistrationProcedureStep(); }
/// <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; }
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); }
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>(); }
public Protocol(Procedure procedure) : this() { _procedures.Add(procedure); procedure.Protocols.Add(this); }
public RegistrationProcedureStep(Procedure procedure) : base(procedure) { }
public ReportingProcedureStep(Procedure procedure, ReportPart reportPart) :base(procedure) { _reportPart = reportPart; }
/// <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); }