maintenance: title: Create Order Reconcile Requirement Main MLM;; mlmname: SCH_CREATE_RECON_RQMT_MAIN;; arden: version 2.5;; version: 5.00;; // SP1 institution: Eclipsys, Standard MLM;; author: Eclipsys Corporation;; specialist: ;; date: 2008-04-23;; validation: testing;; library: purpose: This MLM creates Requirements for Order Reconciliation based on site defined policies. ;; explanation: This MLM creates Order Reconciliation Requirements based on site policies that the site defines in the functional MLMs called by this MLM. Once created these Requirements are used to set a flag on the Patient List to indicate whether Order Reconciliation is due or overdue. When Orders are reconciled, the Reconciliation is linked to the Requirement. Note : the Order Reconciliation can occur before the Requirement is created. If this is the case, the application links the Requirement to the Order Reconciliation using the data stored for each requirement created by the MLM. The CDS Trigger Events where this MLM will be evoked are as follows: . Admit a patient to a specific Facility, Location Function Group or a particular Location Group . Transfer patient from a specific Facility, Location Function Group or a particular Location Group to a specific Facility, Location Function Group or a particular Location Group . Transfer patient to a specific VisitType\Care Level\Service . Transfer patient to a specific Provider on particular units . Discharge a patient from a specific Facility, Location Function Group or a particular Location Group . Enter a ?discharge? order from a specific Facility, Location Function Group or a particular Location Group . Enter a ?transfer? order from a specific Facility, Location Function Group or a particular Location Group to a specific Facility, Location Function Group or a particular Location Group This MLM writes to the Destination only when the MLM concludes TRUE to ensure that the Requirement is only created when the user has proceeded beyond any possible Alerts to save the data to the database. Based on ?rules? defined in this MLM, the logic will determine: . When a Reconciliation Requirement is to be created . What type of Reconciliation can be linked to the Requirement being created . What the time frame is used for linking an Order Reconciliation to a Requirement . When the Reconciliation is to be considered overdue . The locations, Location Function Groups, and Facilities that use a given rule . The various VisitType/CareLevel/Service changes that use a given rule . The various Provider Type and Role changes that use a given rule . Various Orders for transfer and discharge that use a given rule bases on the class associated with the item in the Item Catalog To support their own site policies for when Order Reconciliation should be performed, sites must code their preferences for these {{{SINGLE-QUOTE}}}rules{{{SINGLE-QUOTE}}} in the supporting Functional MLMs. The order - class associations must be configured in the Item Catalog. The MLM will create the Requirement using these site policy definitions. In order to populate the Reconciliation Requirement, the MLM will pass the following information to the Eclipsys function. . The ClientGUID . The ChartGUID . The ClientVisitGUID from the Evoking Object . Type of the reconciliation requirement. Seven types are supported: - Admission, - Location Change - Care Provider Change, - Visit Type\Care Level\Service Change - Discharge - Transfer - Transfer Order - Discharge Order . List of facility defined Reconciliation types. . Precedence for this Requirement. . Timeframe in which this Requirement should be linked. . DateTime after which the Requirement becomes inactive. . Timeframe in which the Requirement and a previous Order Reconciliation can be auto-linked. . DateTime after which the requirement will become overdue. . GUID of the Order that was for a Transfer or Discharge . FromGUID1 and ToGUID1 - For Location Change or Transfer Order, this is the LOcationGUID from the backup ClientVisit and the LocationGUID for the Current ClientVisit. - For Care Provider Change, this is the backup CareProviderVisitRoleGUID and the current CareProviderVisitRoleGUID - For Visit Type/Care Level/Service Change, this is the GUID of the VisitType\Care Level\Service for the backup Clientvisit and the GUID of the VisitType\Care Level\Service for the current ClientVisit. ;; keywords: Order Reconciliation; Policy ;; knowledge: type: data-driven;; data: // Specify which .NET assemblies need to be loaded for ObjectsPlus standard_libs := MLM {{{SINGLE-QUOTE}}}std_include_libs{{{SINGLE-QUOTE}}}; include standard_libs; /***************Make Changes To Spelling And Flags In This Section*******************/ // Set to true if logging is needed. log_execution_info := false; // ---------------------------------------------------------------------------------- // Event Statements // --------------------------------------------------------------------------------- // To enhance efficiency add filtering clauses where ever possible. For example add a // WHERE clause limiting the Event to match the data configured in the supporting // MLM policy definitions. //Transfer - add the locations defined in the transfer policy to enhance efficiency //Visit Type, Care Level or Service - add various VistTypes to enhance efficiency client_visit_modify_event := EVENT { ClientVisitModify Any ClientVisit}; //WHERE TypeCode in ( "Inpatient" )}; //Discharge - add locations that are defined in the discharge policy. client_visit_discharge_event := EVENT { ClientVisitDischarge Any ClientVisit}; //WHERE TypeCode in ( "Inpatient" )}; order_enter_event := EVENT {OrderEnter Any Order: WHERE first of ( OrderCatalogMasterItem.CatalogClassTypeValue.Records__ WHERE OrderCatalogMasterItem.CatalogClassTypeValue.Records__.Code ="ECLP-Reconciliation Order Type" AND OrderCatalogMasterItem.CatalogClassTypeValue.Records__.Value = "Discharge Order" ) is not null }; order_modify_event := EVENT {OrderModify Any Order: WHERE first of ( OrderCatalogMasterItem.CatalogClassTypeValue.Records__ WHERE OrderCatalogMasterItem.CatalogClassTypeValue.Records__.Code ="ECLP-Reconciliation Order Type" AND OrderCatalogMasterItem.CatalogClassTypeValue.Records__.Value = "Discharge Order" ) is not null }; using "ObjectsPlusXA.SCM.Forms"; using namespace "ObjectsPlusXA.SunriseClinicalManager.Forms"; // Flag on how to handle multiple occurences of the same provider role type // (This flag is only applicable when SCMCareProviderRoleType is configured to allow multiple) // (If SCMCareProviderRoleType does not allow multiple, check for valid policy always happen) // If TRUE - check for valid policy for first occurrence only // If FALSE - check for valid policy for all occurrences handle_first_multi_provider_occurrence_flag := TRUE; // Error message text can be editted as needed error_destination := destination { Alert: reminder, "Error in order reconciliation", medium, chart }; /**************************Do not make changes below this Section**********************/ //A variable used to check if a policy record is found policy_record_found := false; //A variable used to store order reconciliation requirement my_req := Null; my_req_list := (); //A variable used to store policy definition policy_def := null; policydef_list := (); // Used when running from the editor if called_by_editor then EvokingObject := read last { ClientVisit: This}; //EvokingEvent := client_visit_enter_event; // Admission Event //EvokingEvent := client_visit_modify_event; // Transfer Event, Service Change Event //EvokingEvent := client_visit_discharge_event; // Discharge Event //EvokingObject := read last { Order: This}; //EvokingEvent := order_enter_event; // Order Transfer, Order Discharge Event //EvokingEvent := order_modify_event; // Order Transfer, Order Discharge Event //EvokingEvent := order_enter_no_iv_additives_event; // Order Transfer Event //EvokingEvent := order_init_event; // Order Discharge Event //EvokingObject := read last { CareProviderVisitRole: This}; //EvokingEvent := provider_enter_event; // Care Provider Change endif; // if called_by_editor // Declare policy specific MLMs that can be called AdmissionPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_ADMISSIONPOLICY{{{SINGLE-QUOTE}}}; // TransferPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_TRANSFERPOLICY{{{SINGLE-QUOTE}}}; // DischargePolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_DISCHARGEPOLICY{{{SINGLE-QUOTE}}}; // CareProviderChangePolicy_MLM // := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_CAREPROVIDERCHANGEPOLICY{{{SINGLE-QUOTE}}}; OrderDischargePolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_ORDERDISCHARGEPOLICY{{{SINGLE-QUOTE}}}; // OrderTransferPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_ORDERTRANSFERPOLICY{{{SINGLE-QUOTE}}}; // VisitTypeCareLevelServicePolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_VISITTYPECARELEVELSERVICEPOLICY{{{SINGLE-QUOTE}}}; SelectPatientLocPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_SelectPatientLocPolicy{{{SINGLE-QUOTE}}}; // SelectTransferPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_SelectTransferPolicy{{{SINGLE-QUOTE}}}; // SelectCareProviderPolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_SelectCareProviderPolicy{{{SINGLE-QUOTE}}}; // SelectServicePolicy_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_SelectServicePolicy{{{SINGLE-QUOTE}}}; SetDefault_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_RECON_RQMT_SET_POLICY_DEFAULT{{{SINGLE-QUOTE}}}; error_occured := false; overridebyloc := false; //Determine the type of event and perform logic for that event // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 1" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; //**************************// // // // Admission Event SCH changed to transfer from ER Major only // // // //**************************// if EvokingEvent = client_visit_modify_event then // RS 05/10/2010 Added to find previous location (backup_obj) := read last {ClientVisit: Backup REFERENCING EvokingObject}; (Bk_Loc_Name, Bk_Loc_GUID, Bk_VisitStatus,Bk_TypeCode,Bk_TemporaryLocation) := read last {ClientVisit: CurrentLocation,CurrentLocationGUID,VisitStatus,TypeCode, TemporaryLocation REFERENCING backup_obj}; // RS 05/10/2010 end of addition //Get Required parameters from the evoking object ( visit_client_guid, visit_guid, visit_chart_guid, visit_location_guid, alternate_visit_location_guid, visit_loc_name) := read last {ClientVisit: ClientGUID, GUID, ChartGUID, BusinessRuleLocationGUID, CurrentLocationGUID, currentlocation REFERENCING EvokingObject} ; // RS added to insure that to location is an inpatient bed counter := 0; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "From Location " || Bk_Loc_Name || "\n\n To Location " || visit_loc_name // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; counter := read last {" select count(*) from Cv3Location with (nolock) " || " where locngrpguid = " || alternate_visit_location_guid || " and name = " || sql(visit_loc_name) || " and typecode = {{{SINGLE-QUOTE}}}Bed{{{SINGLE-QUOTE}}} " || " and active = 1 " }; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 2" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; if ((Bk_Loc_Name <> "ER Major") or (counter =0)) then overridebyloc := true; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "I should not create a flag as from loc is " || Bk_Loc_Name || "\n\n and to bed is " || counter // ,"Tester","YesNo" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; else // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 3" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "I should create a flag as from loc is " || Bk_Loc_Name || "\n\n and to bed is " || counter // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; // RS 05/10/2010 added to here, note the extra if above // Will only fire if coming from ER Major and going to a bed //Ensure location guid value is filled in, if not, use alternate value if (visit_location_guid is NULL) then visit_location_guid := alternate_visit_location_guid; endif; //Check for existing policy definition (AdmissionPolicyListDef, AdmissionPolicyDefaults):= call AdmissionPolicy_MLM; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 4" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; //When a patient is admitted, determine if //order reconciliation requirement needs to be created. policy_def := call SelectPatientLocPolicy_MLM with visit_location_guid, AdmissionPolicyListDef; //check for default values policy_def:= call SetDefault_MLM with policy_def,AdmissionPolicyDefaults; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 5" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; //Intentionally left for support purposes //eventName:= "Admission"; //break; if (policy_def is NOT NULL) then policy_record_found := true; try reconcileList := policy_def.ReconcileType; reconcileTypeColl:= new net_object {{{SINGLE-QUOTE}}}ReconcileTypeCollection{{{SINGLE-QUOTE}}}; //dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 6" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; index_list := 1 seqto (count reconcileList); for ind in index_list do void := call reconcileTypeColl.Add with ( reconcileList[ind] as {{{SINGLE-QUOTE}}}String{{{SINGLE-QUOTE}}}); enddo; //ind in index_list do //dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 7" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; // create ObjectsPlus OrderReconciliationRequirement object my_req := call {{{SINGLE-QUOTE}}}OrderReconciliationRequirement{{{SINGLE-QUOTE}}}.CreateAdmissionRequirement with ((visit_client_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}), ((visit_chart_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}), ((visit_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}), reconcileTypeColl; // dialogResult := call {{{SINGLE-QUOTE}}}MessageBox{{{SINGLE-QUOTE}}}.Show with "Marker 8" // ,"Tester","Ok" as {{{SINGLE-QUOTE}}}MessageBoxButtons{{{SINGLE-QUOTE}}}; my_req_list := my_req,my_req_list; policydef_list := policy_def,policydef_list; endtry; catch exception ex my_exception := ex; error_occured := True; endcatch; endif; // override location change endif; // if(policy_def is NOT NULL) //**************************// // // // Discharge Order Event // // // //**************************// elseif ( (EvokingEvent = order_enter_event) OR (EvokingEvent = order_modify_event) ) then //Gets information from the evoking Order (visit_guid, order_guid, Ord) := read last {Order: ClientVisitGUID, GUID, This REFERENCING EvokingObject}; transfer_to_location := Ord.OrderAdditionalInfo.TransferToLocnGUID; //Get Required parameters from the ClientVisitObject object ( type_code) := read last {ClientVisit: TypeCode Where GUID = visit_guid } ; ( visit_client_guid, visit_chart_guid, visit_location_guid, alternate_visit_location_guid, new_visit_location_guid) := read last {ClientVisit: ClientGUID, ChartGUID, BusinessRuleLocationGUID, CurrentLocationGUID, NextLocnGrpGUID, Where GUID = visit_guid } ; //Ensure location guid value is filled in, if not, use alternate value if (visit_location_guid is NULL) then visit_location_guid := alternate_visit_location_guid; endif; //Get Order Class Type ocmi := Read last {Order: OrderCatalogMasterItem referencing Ord}; orderRecCatalogClassTypeValue := first of (ocmi.CatalogClassTypeValue.Records__ where ocmi.CatalogClassTypeValue.Records__.code = "ECLP-Reconciliation Order Type" ); classTypeValue := orderRecCatalogClassTypeValue.value; if (classTypeValue="Discharge Order") then //Check for existing policy definition (OrderDischargePolicyListDef, OrderDischargePolicyDefaults):= call OrderDischargePolicy_MLM; //When a discharge order is placed, determine if //order reconciliation requirement needs to be created. policy_def := call SelectPatientLocPolicy_MLM with visit_location_guid, OrderDischargePolicyListDef; //check for default values policy_def:= call SetDefault_MLM with policy_def,OrderDischargePolicyDefaults; //Intentionally left for support purposes //eventName:= "Order Discharge"; //break; endif; if (policy_def is NOT NULL) then policy_record_found := true; try // get current client visit object client_visit := call {{{SINGLE-QUOTE}}}ClientVisit{{{SINGLE-QUOTE}}}.FindByPrimaryKey with ((visit_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}); reconcileTypeColl:= new net_object {{{SINGLE-QUOTE}}}ReconcileTypeCollection{{{SINGLE-QUOTE}}}; reconcileList := policy_def.ReconcileType; index_list := 1 seqto (count reconcileList); for ind in index_list do void := call reconcileTypeColl.Add with ( reconcileList[ind] as {{{SINGLE-QUOTE}}}String{{{SINGLE-QUOTE}}}); enddo; //ind in index_list do if (classTypeValue = "Transfer Order") then my_req := call {{{SINGLE-QUOTE}}}OrderReconciliationRequirement{{{SINGLE-QUOTE}}}.CreateTransferOrderRequirement with client_visit, reconcileTypeColl, ((order_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}), ((visit_location_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}), ((transfer_to_location as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}); elseif (classTypeValue="Discharge Order") then my_req := call {{{SINGLE-QUOTE}}}OrderReconciliationRequirement{{{SINGLE-QUOTE}}}.CreateDischargeOrderRequirement with client_visit, reconcileTypeColl, ((order_guid as number) as {{{SINGLE-QUOTE}}}Int64{{{SINGLE-QUOTE}}}); endif; if ( client_visit is NOT NULL ) then void:= call client_visit.Dispose; client_visit:= null; endif; my_req_list := my_req,my_req_list; policydef_list := policy_def,policydef_list; endtry; catch exception ex my_exception := ex; if ( client_visit is NOT NULL ) then void:= call client_visit.Dispose; client_visit:= null; endif; index_list := 1 seqto (count my_req_list); for ind in index_list do req_obj := my_req_list[ind]; if ( req_obj is NOT NULL ) then void:= call req_obj.Dispose; req_obj:= null; endif; enddo; endcatch; endif; // if(policy_def is NOT NULL) endif; //if EvokingEvent = client_visit_enter_event //******************************// // // // Populate Requirement // // // //******************************// //populate order reconciliation requirement with values if (policy_record_found) then index_list := 1 seqto count(my_req_list); for ind in index_list do req := my_req_list[ind]; def := policydef_list[ind]; if (def.AutoLinkTimeFrame is not Null) then req.AutoLinkTimeframeHours := def.AutoLinkTimeFrame as {{{SINGLE-QUOTE}}}System.Int32{{{SINGLE-QUOTE}}}; endif; if (def.RequirementPrecedence is not Null) then req.Precedence := def.RequirementPrecedence as {{{SINGLE-QUOTE}}}System.Int32{{{SINGLE-QUOTE}}}; endif; if (def.RequirementPrecedenceTime is not Null) then req.PrecedenceTimeframeHours := def.RequirementPrecedenceTime as {{{SINGLE-QUOTE}}}System.Int32{{{SINGLE-QUOTE}}}; endif; if (def.OverDueDtmHours is not Null) then req.OverdueAfter := (NOW + (def.OverDueDtmHours hours)) as {{{SINGLE-QUOTE}}}System.DateTime{{{SINGLE-QUOTE}}}; endif; if (def.RequirementCleanupDtmHours is not Null) then req.InactivateAfter := (NOW + (def.RequirementCleanupDtmHours hours)) as {{{SINGLE-QUOTE}}}System.DateTime{{{SINGLE-QUOTE}}}; endif; //Define the XA Object Destination for Requirement Reqt_Destination:= destination { XAObject } with [xaobject := req]; enddo; // ind in index_list do endif; //if(policy_record_found) ;; evoke: // client_visit_modify_event OR //client_visit_discharge_event OR order_enter_event OR order_modify_event ;; logic: if (policy_record_found) and (overridebyloc = false) then conclude TRUE; else conclude FALSE; endif //(policy_record_found) ;; action: if (error_occured) then write my_exception at error_destination; else Write true at Reqt_Destination ; endif; //(error_occured) ;; Urgency: 50;; end: