unit fODBase; {$OPTIMIZATION OFF} // REMOVE AFTER UNIT IS DEBUGGED interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, fAutoSz, StdCtrls, ORCtrls, ORFn, uConst, rOrders, rODBase, uCore, ComCtrls, ExtCtrls, Menus, Mask, Buttons, UBAGlobals, UBACore; type TCtrlInit = class private Name: string; Text: string; ListID: string; List: TStringList; public constructor Create; destructor Destroy; override; end; TCtrlInits = class private FDfltList: TList; FOIList: TList; procedure ExtractInits(Src: TStrings; Dest: TList); function FindInitByName(const AName: string): TCtrlInit; public constructor Create; destructor Destroy; override; procedure ClearOI; function DefaultText(const ASection: string): string; procedure LoadDefaults(Src: TStrings); procedure LoadOrderItem(Src: TStrings); procedure SetControl(AControl: TControl; const ASection: string); procedure SetListOnly(AControl: TControl; const ASection: string); procedure SetPopupMenu(AMenu: TPopupMenu; AClickEvent: TNotifyEvent; const ASection: string); function TextOf(const ASection: string): string; end; TResponses = class private FDialog: string; FResponseList: TList; FPrompts: TList; FCopyOrder: string; FEditOrder: string; FTransferOrder: string; FDisplayGroup: Integer; FQuickOrder: Integer; FOrderChecks: TStringList; FVarLeading: string; FVarTrailing: string; FEventType: Char; FEventIFN: Integer; FEventName: string; FSpecialty: Integer; FEffective: TFMDateTime; FParentEvent: TParentEvent; FLogTime: TFMDateTime; FViewName: string; FCancel: boolean; FOrderContainsObjects: boolean; function FindResponseByIEN(APromptIEN, AnInstance: Integer): TResponse; function GetOrderText: string; function IENForPrompt(const APromptID: string): Integer; procedure SetDialog(Value: string); procedure SetCopyOrder(const AnID: string); procedure SetEditOrder(const AnID: string); procedure SetQuickOrder(AnIEN: Integer); procedure SetQuickOrderByID(const AnID: string); procedure FormatResponse(var FormattedText: string; var ExcludeText: Boolean; APrompt: TPrompt; const x: string; AnInstance: Integer); function FindPromptByIEN(AnIEN: Integer): TPrompt; procedure AppendChildren(var ParentText: string; ChildPrompts: string; AnInstance: Integer); procedure BuildOCItems(AList: TStringList; var AStartDtTm: string; const AFillerID: string); public constructor Create; destructor Destroy; override; procedure Clear; overload; procedure Clear(const APromptID: string; SaveInstance: Integer = 0); overload; function EValueFor(const APromptID: string; AnInstance: Integer): string; function GetIENForPrompt(const APromptID: string): Integer; function FindResponseByName(const APromptID: string; AnInstance: Integer): TResponse; function PromptExists(const APromptID: string):boolean; function InstanceCount(const APromptID: string): Integer; function IValueFor(const APromptID: string; AnInstance: Integer): string; function NextInstance(const APromptID: string; LastInstance: Integer): Integer; function OrderCRC: string; procedure Remove(const APromptID: string; AnInstance: Integer); procedure SaveQuickOrder(var ANewIEN: Integer; const ADisplayName: string); procedure SaveOrder(var AnOrder: TOrder; DlgIEN: Integer; IsIMOOrder: boolean = False); procedure SetControl(AControl: TControl; const APromptID: string; AnInstance: Integer); procedure SetEventDelay(AnEvent: TOrderDelayEvent); procedure SetPromptFormat(const APromptID, NewFormat: string); procedure Update(const APromptID: string; AnInstance: Integer; const AnIValue, AnEValue: string); property Dialog: string read FDialog write SetDialog; property DisplayGroup: Integer read FDisplayGroup write FDisplayGroup; property CopyOrder: string read FCopyOrder write SetCopyOrder; property EditOrder: string read FEditOrder; // write SetEditOrder; property TransferOrder:string read FTransferOrder write FTransferOrder; property EventType: Char read FEventType; property EventIFN: integer read FEventIFN write FEventIFN; property EventName: string read FEventName write FEventName; property LogTime: TFMDateTime read FLogTime write FLogTime; property QuickOrder: Integer read FQuickOrder write SetQuickOrder; property OrderChecks: TStringList read FOrderChecks write FOrderChecks; property OrderText: string read GetOrderText; property VarLeading: string read FVarLeading write FVarLeading; property VarTrailing: string read FVarTrailing write FVarTrailing; property TheList: TList read FResponseList write FResponseList; property Cancel: boolean read FCancel write FCancel; property OrderContainsObjects: boolean read FOrderContainsObjects write FOrderContainsObjects; end; TCallOnExit = procedure; TfrmODBase = class(TfrmAutoSz) memOrder: TCaptionMemo; cmdAccept: TButton; cmdQuit: TButton; pnlMessage: TPanel; imgMessage: TImage; memMessage: TRichEdit; procedure cmdQuitClick(Sender: TObject); procedure cmdAcceptClick(Sender: TObject); procedure FormKeyPress(Sender: TObject; var Key: Char); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure memMessageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure pnlMessageExit(Sender: TObject); procedure pnlMessageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure pnlMessageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); private FIsSupply: Boolean; FAbortOrder: Boolean; FAllowQO: Boolean; FAutoAccept: Boolean; FClosing: Boolean; FChanging: Boolean; FDialogIEN: Integer; FDisplayGroup: Integer; FFillerID: string; FFromQuit: Boolean; FAcceptOK: Boolean; FCtrlInits: TCtrlInits; FResponses: TResponses; FPreserve: TList; FRefNum: Integer; FOrderAction: Integer; FKeyVariables: string; FCallOnExit: TCallOnExit; FTestMode: Boolean; FDlgFormID: Integer; FDfltCopay: String; FEvtForPassDischarge: Char; FEvtID : Integer; FEvtType : Char; FEvtName : string; FIncludeOIPI: boolean; FIsIMO: boolean; //imo FMessageClickX: integer; FMessageClickY: integer; function AcceptOrderChecks: Boolean; procedure ClearDialogControls; function GetKeyVariable(const Index: string): string; function GetEffectiveDate: TFMDateTime; procedure SetDisplayGroup(Value: Integer); procedure SetFillerID(const Value: string); procedure DoSetFontSize( FontSize: integer); protected function LESValidationCheck: boolean; procedure InitDialog; virtual; procedure SetDialogIEN(Value: Integer); virtual; procedure Validate(var AnErrMsg: string); virtual; function ValidSave: Boolean; procedure ShowOrderMessage(Show: boolean); public function OrderForInpatient: Boolean; procedure SetDefaultCoPay(AnOrderID: string); procedure OrderMessage(const AMessage: string); procedure PreserveControl(AControl: TControl); procedure SetupDialog(OrderAction: Integer; const ID: string); virtual; procedure SetFontSize( FontSize: integer); virtual; procedure SetKeyVariables(const VarStr: string); procedure TabClose(var CanClose: Boolean); property AbortOrder: Boolean read FAbortOrder write FAbortOrder; property AcceptOK: Boolean read FAcceptOK; property AllowQuickOrder: Boolean read FAllowQO write FAllowQO; property AutoAccept: Boolean read FAutoAccept write FAutoAccept; property CallOnExit: TCallOnExit read FCallOnExit write FCallOnExit; property Changing: Boolean read FChanging write FChanging; property Closing: Boolean read FClosing; property CtrlInits: TCtrlInits read FCtrlInits write FCtrlInits; property DialogIEN: Integer read FDialogIEN write SetDialogIEN; property DisplayGroup: Integer read FDisplayGroup write SetDisplayGroup; property EffectiveDate: TFMDateTime read GetEffectiveDate; property FillerID: string read FFillerID write SetFillerID; property KeyVariable[const Index: string]: string read GetKeyVariable; property RefNum: Integer read FRefNum write FRefNum; property Responses: TResponses read FResponses write FResponses; property TestMode: Boolean read FTestMode write FTestMode; property DlgFormID: Integer read FDlgFormID write FDlgFormID; property DfltCopay: string read FDfltCopay write FDfltCopay; property EvtForPassDischarge: Char read FEvtForPassDischarge write FEvtForPassDischarge; property EvtID: integer read FEvtID write FEvtID; property EvtType: Char read FEvtType write FEvtType; property EvtName: String read FEvtName write FEvtName; property IncludeOIPI: boolean read FIncludeOIPI write FIncludeOIPI; property IsIMO:boolean read FIsIMO write FIsIMO; property IsSupply: boolean read FIsSupply write FIsSupply; end; var frmODBase: TfrmODBase; XfInToOutNow :boolean = False; // it's used only for transfering Inpatient Meds to OutPatient Med for // immediately release (NO EVENT DELAY) XferOuttoInOnMeds : boolean = False; // it's used only for transfering Outpatient Meds to Inpatient Med for // immediately release (NO EVENT DELAY) ImmdCopyAct: boolean = False; IsUDGroup: boolean = False; // it's only used for copy inpatient med order. DEASig: string; // digital signature DupORIFN: string; // it's used to identify the order number for duplicate orders in order checking NoFresh: boolean = False; // EDO use only SaveAsCurrent: boolean = False; // EDO use only CIDCOkToSave: boolean; // CIDC only, used for consult orders. OrderSource: string = ''; EventDefaultOD: integer = 0; // If it's event default dialog? IsTransferAction: boolean = False; procedure ClearControl(AControl: TControl); procedure ResetControl(AControl: TControl); implementation {$R *.DFM} uses fOCAccept, uODBase, rCore, rMisc, fODMessage, fTemplateDialog, uEventHooks, uTemplates, rConsults,fOrders,uOrders, fFrame, uTemplateFields, fClinicWardMeds; const TX_ACCEPT = 'Accept the following order?' + CRLF + CRLF; TX_ACCEPT_CAP = 'Unsaved Order'; TC_ORDERCHECKS = 'Order Checks'; { Procedures shared with descendent forms } procedure ClearControl(AControl: TControl); { clears a control, removes text and listbox items } begin if AControl is TLabel then with TLabel(AControl) do Caption := '' else if AControl is TStaticText then with TStaticText(AControl) do Caption := '' else if AControl is TButton then with TButton(AControl) do Caption := '' else if AControl is TEdit then with TEdit(AControl) do Text := '' else if AControl is TMemo then with TMemo(AControl) do Clear else if AControl is TRichEdit then with TRichEdit(AControl) do Clear else if AControl is TORListBox then with TORListBox(AControl) do Clear else if AControl is TListBox then with TListBox(AControl) do Clear else if AControl is TORComboBox then with TORComboBox(AControl) do begin Items.Clear; Text := ''; end else if AControl is TComboBox then with TComboBox(AControl) do begin Clear; Text := ''; end; end; procedure ResetControl(AControl: TControl); { clears text, deselects items, does not remove listbox or combobox items } begin if AControl is TLabel then with TLabel(AControl) do Caption := '' else if AControl is TStaticText then with TStaticText(AControl) do Caption := '' else if AControl is TButton then with TButton(AControl) do Caption := '' else if AControl is TEdit then with TEdit(AControl) do Text := '' else if AControl is TMemo then with TMemo(AControl) do Clear else if AControl is TRichEdit then with TRichEdit(AControl) do Clear else if AControl is TListBox then with TListBox(AControl) do ItemIndex := -1 else if AControl is TORComboBox then with TORComboBox(AControl) do begin Text := ''; ItemIndex := -1; end else if AControl is TComboBox then with TComboBox(AControl) do begin Text := ''; ItemIndex := -1; end; end; { TCtrlInit methods } constructor TCtrlInit.Create; begin List := TStringList.Create; end; destructor TCtrlInit.Destroy; begin List.Free; inherited Destroy; end; { TCtrlInits methods } constructor TCtrlInits.Create; { create lists to store initial value for dialog and selected orderable item } begin FDfltList := TList.Create; FOIList := TList.Create; end; destructor TCtrlInits.Destroy; { free the objects used to store initialization information } var i: Integer; begin { free the objects in the lists first } with FDfltList do for i := 0 to Count - 1 do TCtrlInit(Items[i]).Free; FDfltList.Free; ClearOI; FOIList.Free; inherited Destroy; end; procedure TCtrlInits.ClearOI; { clears the records in FOIList, but not FDfltList } var i: Integer; begin with FOIList do for i := 0 to Count - 1 do TCtrlInit(Items[i]).Free; FOIList.Clear; end; procedure TCtrlInits.ExtractInits(Src: TStrings; Dest: TList); { load a list with TCtrlInit records (source strings are those passed from server } var i: Integer; ACtrlInit: TCtrlInit; begin i := 0; while i < Src.Count do begin if CharAt(Src[i], 1) = '~' then begin ACtrlInit := TCtrlInit.Create; with ACtrlInit do begin Name := Copy(Src[i], 2, Length(Src[i])); List := TStringList.Create; Inc(i); while (i < Src.Count) and (CharAt(Src[i], 1) <> '~') do begin if CharAt(Src[i], 1) = 'i' then List.Add(Copy(Src[i], 2, 255)); if CharAt(Src[i], 1) = 't' then List.Add(Copy(Src[i], 2, 255)); if CharAt(Src[i], 1) = 'd' then begin Text := Piece(Src[i], U, 2); ListID := Copy(Piece(Src[i], U, 1), 2, 255); end; Inc(i); end; {while i & CharAt...} Dest.Add(ACtrlInit); end; {with ACtrlDflt} end; {if CharAt} end; {while i} end; procedure TCtrlInits.LoadDefaults(Src: TStrings); { loads control initialization information for the dialog } begin FDfltList.Clear; ExtractInits(Src, FDfltList); end; procedure TCtrlInits.LoadOrderItem(Src: TStrings); { loads control initialization information for the orderable item } begin ClearOI; ExtractInits(Src, FOIList); end; function TCtrlInits.FindInitByName(const AName: string): TCtrlInit; { look first in FOIList, then in FDfltList for initial values identified by name (~section) } var i: Integer; begin Result := nil; with FOIList do for i := 0 to Count - 1 do if TCtrlInit(Items[i]).Name = AName then begin Result := TCtrlInit(Items[i]); break; end; if Result = nil then with FDfltList do for i := 0 to Count - 1 do if TCtrlInit(Items[i]).Name = AName then begin Result := TCtrlInit(Items[i]); break; end; end; procedure TCtrlInits.SetControl(AControl: TControl; const ASection: string); { initializes a control to the information in a section (~section from server) } var CtrlInit: TCtrlInit; begin ClearControl(AControl); CtrlInit := FindInitByName(ASection); if CtrlInit = nil then Exit; if AControl is TLabel then with TLabel(AControl) do Caption := CtrlInit.Text else if AControl is TStaticText then with TStaticText(AControl) do Caption := CtrlInit.Text else if AControl is TButton then with TButton(AControl) do Caption := CtrlInit.Text else if AControl is TEdit then with TEdit(AControl) do Text := CtrlInit.Text else if AControl is TMemo then with TMemo(AControl) do Lines.Assign(CtrlInit.List) else if AControl is TRichEdit then with TRichEdit(AControl) do Lines.Assign(CtrlInit.List) else if AControl is TORListBox then with TORListBox(AControl) do Items.Assign(CtrlInit.List) else if AControl is TListBox then with TListBox(AControl) do Items.Assign(CtrlInit.List) else if AControl is TComboBox then with TComboBox(AControl) do begin Items.Assign(CtrlInit.List); Text := CtrlInit.Text; end else if AControl is TORComboBox then with TORComboBox(AControl) do begin Items.Assign(CtrlInit.List); if LongList then InitLongList(Text) else Text := CtrlInit.Text; SelectByID(CtrlInit.ListID); end; { need to add SelectByID for combobox & listbox } end; procedure TCtrlInits.SetListOnly(AControl: TControl; const ASection: string); { assigns list portion to a control from a section (used to set ShortList for meds) } var CtrlInit: TCtrlInit; begin CtrlInit := FindInitByName(ASection); if CtrlInit = nil then Exit; if AControl is TMemo then with TMemo(AControl) do Lines.Assign(CtrlInit.List) else if AControl is TORListBox then with TORListBox(AControl) do Items.Assign(CtrlInit.List) else if AControl is TListBox then with TListBox(AControl) do Items.Assign(CtrlInit.List) else if AControl is TComboBox then with TComboBox(AControl) do Items.Assign(CtrlInit.List) else if AControl is TORComboBox then with TORComboBox(AControl) do Items.Assign(CtrlInit.List); end; procedure TCtrlInits.SetPopupMenu(AMenu: TPopupMenu; AClickEvent: TNotifyEvent; const ASection: string); { populates a popup menu with items in a list, leaves the maximum text width in Tag } var i, MaxWidth: Integer; CtrlInit: TCtrlInit; AMenuItem: TMenuItem; begin CtrlInit := FindInitByName(ASection); // clear the current menu entries for i := AMenu.Items.Count - 1 downto 0 do begin AMenuItem := AMenu.Items[i]; if AMenuItem <> nil then begin AMenu.Items.Delete(i); AMenuItem.Free; end; end; MaxWidth := 0; for i := 0 to CtrlInit.List.Count - 1 do begin AMenuItem := TMenuItem.Create(Application); AMenuItem.Caption := CtrlInit.List[i]; AMenuItem.OnClick := AClickEvent; AMenu.Items.Add(AMenuItem); MaxWidth := HigherOf(MaxWidth, Application.MainForm.Canvas.TextWidth(CtrlInit.List[i])); end; AMenu.Tag := MaxWidth; end; function TCtrlInits.DefaultText(const ASection: string): string; var CtrlInit: TCtrlInit; begin Result := ''; CtrlInit := FindInitByName(ASection); if CtrlInit <> nil then Result := CtrlInit.ListID; end; function TCtrlInits.TextOf(const ASection: string): string; var CtrlInit: TCtrlInit; begin Result := ''; CtrlInit := FindInitByName(ASection); if CtrlInit <> nil then Result := CtrlInit.List.Text; end; { TResponses methods } function SortPromptsBySequence(Item1, Item2: Pointer): Integer; { compare function used to sort formatting info by sequence - used by TResponses.SetDialog} var Prompt1, Prompt2: TPrompt; begin Prompt1 := TPrompt(Item1); Prompt2 := TPrompt(Item2); if Prompt1.Sequence < Prompt2.Sequence then Result := -1 else if Prompt1.Sequence > Prompt2.Sequence then Result := 1 else Result := 0; end; constructor TResponses.Create; begin FResponseList := TList.Create; FPrompts := TList.Create; FOrderChecks := TStringList.Create; FEventType := #0; FParentEvent := TParentEvent.Create; FLogTime := 0; end; destructor TResponses.Destroy; { frees all response objects before freeing list } var i: Integer; begin Clear; FOrderChecks.Free; FResponseList.Free; with FPrompts do for i := 0 to Count - 1 do TPrompt(Items[i]).Free; FPrompts.Free; inherited Destroy; end; procedure TResponses.Clear; { clears all information in the response multiple } var i: Integer; begin FVarLeading := ''; FVarTrailing := ''; FQuickOrder := 0; //FCopyOrder := ''; // don't clear FCopyOrder either? // don't clear FEditOrder or it will cause a new order to be created instead of an edit with FResponseList do for i := 0 to Count - 1 do TResponse(Items[i]).Free; FResponseList.Clear; FOrderChecks.Clear; end; procedure TResponses.Clear(const APromptID: string; SaveInstance: Integer = 0); var AResponse: TResponse; i: Integer; begin with FResponseList do for i := Count - 1 downto SaveInstance do begin AResponse := TResponse(Items[i]); if AResponse.PromptID = APromptID then begin AResponse.Free; FResponseList.Delete(i); end; {if AResponse} end; {for} end; procedure TResponses.SetDialog(Value: string); { loads formatting information for a dialog } var i: Integer; begin with FPrompts do for i := 0 to Count - 1 do TPrompt(Items[i]).Free; FPrompts.Clear; FDialog := Value; LoadDialogDefinition(FPrompts, FDialog); FPrompts.Sort(SortPromptsBySequence); end; procedure TResponses.SetCopyOrder(const AnID: string); { sets responses to the values for an order that is created by copying } var HasObjects: boolean; begin if AnID = '' then begin FCopyOrder := AnID; Exit; end; Clear; LoadResponses(FResponseList, AnID, HasObjects); // Example AnID=C123456;1-3604 FCopyOrder := Copy(Piece(AnID, '-', 1), 2, Length(AnID)); FOrderContainsObjects := HasObjects; end; procedure TResponses.SetEditOrder(const AnID: string); { sets responses to the values for an order that is about to be edited } var HasObjects: boolean; begin Clear; LoadResponses(FResponseList, AnID, HasObjects); // Example AnID=X123456;1 FEditOrder := Copy(Piece(AnID, '-', 1), 2, Length(AnID)); FOrderContainsObjects := HasObjects; end; procedure TResponses.SetQuickOrder(AnIEN: Integer); { sets responses to a quick order value - this is used by the QuickOrder property} var HasObjects: boolean; begin Clear; LoadResponses(FResponseList, IntToStr(AnIEN), HasObjects); // Example AnIEN=134 FQuickOrder := AnIEN; FOrderContainsObjects := HasObjects; end; procedure TResponses.SetQuickOrderByID(const AnID: string); { sets responses to a quick order value } var HasObjects: boolean; begin Clear; LoadResponses(FResponseList, AnID, HasObjects); // Example AnID=134-3645 FQuickOrder := StrToIntDef(Piece(AnID, '-', 1), 0); // 2nd '-' piece is $H seconds FOrderContainsObjects := HasObjects; end; procedure TResponses.BuildOCItems(AList: TStringList; var AStartDtTm: string; const AFillerID: string); var i, TheInstance: Integer; OrderableIEN, PkgPart: string; begin if EditOrder <> '' then DupORIFN := EditOrder; if CopyOrder <> '' then DupORIFN := CopyOrder; //if {(CopyOrder <> '') or} (EditOrder <> '') then Exit; // only check new orders with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = 'ORDERABLE') or (PromptID = 'ADDITIVE') then begin OrderableIEN := IValue; TheInstance := Instance; PkgPart := ''; if AFillerID = 'LR' then PkgPart := '^LR^' + IValueFor('SPECIMEN', TheInstance); if (AFillerID = 'PSI') or (AFillerID = 'PSO') or (AFillerID = 'PSH') then PkgPart := U + AFillerID + U + IValueFor('DRUG', TheInstance); // was -- then PkgPart := '^PS^' + IValueFor('DRUG', TheInstance); if AFillerID = 'PSIV' then begin if PromptID = 'ORDERABLE' then PkgPart := '^PSIV^B;' + IValueFor('VOLUME', TheInstance); if PromptID = 'ADDITIVE' then PkgPart := '^PSIV^A'; end; AList.Add(OrderableIEN + PkgPart); end; AStartDtTm := IValueFor('START', 1); end; function TResponses.EValueFor(const APromptID: string; AnInstance: Integer): string; var i: Integer; begin Result := ''; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = APromptID) and (Instance = AnInstance) then begin Result := EValue; break; end; end; function TResponses.IValueFor(const APromptID: string; AnInstance: Integer): string; var i: Integer; begin Result := ''; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = APromptID) and (Instance = AnInstance) then begin Result := IValue; break; end; end; function TResponses.PromptExists(const APromptID: string): boolean; var i: Integer; begin Result := False; with FPrompts do for i := 0 to Count - 1 do with TPrompt(Items[i]) do if (ID = APromptID) then Result := True; end; function TResponses.FindResponseByName(const APromptID: string; AnInstance: Integer): TResponse; var i: Integer; begin Result := nil; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = APromptID) and (Instance = AnInstance) then begin Result := TResponse(Items[i]); break; end; end; function TResponses.IENForPrompt(const APromptID: string): Integer; var i: Integer; begin Result := 0; with FPrompts do for i := 0 to Count - 1 do with TPrompt(Items[i]) do if (ID = APromptID) then begin Result := IEN; break; end; end; function TResponses.InstanceCount(const APromptID: string): Integer; var i: Integer; begin Result := 0; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = APromptID) then Inc(Result); end; function TResponses.NextInstance(const APromptID: string; LastInstance: Integer): Integer; var i: Integer; begin Result := 0; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptID = APromptID) and (Instance > LastInstance) and ((Result = 0) or ((Result > 0) and (Instance < Result))) then Result := Instance; end; function TResponses.FindResponseByIEN(APromptIEN, AnInstance: Integer): TResponse; var i: Integer; begin Result := nil; with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do if (PromptIEN = APromptIEN) and (Instance = AnInstance) then begin Result := TResponse(Items[i]); break; end; end; procedure TResponses.FormatResponse(var FormattedText: string; var ExcludeText: Boolean; APrompt: TPrompt; const x: string; AnInstance: Integer); var AValue: string; PromptIEN: Integer; Related: TResponse; begin FormattedText := ''; ExcludeText := True; with APrompt do begin if FmtCode = '@' then Exit; // skip this response if CharAt(FmtCode, 1) = '@' then // exclude if related response exists begin PromptIEN := StrToIntDef(Copy(FmtCode, 2, Length(FmtCode)), 0); if (FindResponseByIEN(PromptIEN, AnInstance) <> nil) then Exit; end; if CharAt(FmtCode, 1) = '*' then // include if related response exists begin PromptIEN := StrToIntDef(Copy(FmtCode, 2, Length(FmtCode)), 0); if FindResponseByIEN(PromptIEN, AnInstance) = nil then Exit; end; if CharAt(FmtCode, 1) = '#' then // include if related response = value begin AValue := Copy(FmtCode, Pos('=', FmtCode) + 1, Length(FmtCode)); PromptIEN := StrToIntDef(Copy(Piece(FmtCode, '=', 1), 2, Length(FmtCode)), 0); Related := FindResponseByIEN(PromptIEN, AnInstance); if Related = nil then Exit; if not (Related.EValue = AValue) then Exit; end; if CharAt(FmtCode, 1) = '=' then // exclude if related response has same text begin PromptIEN := StrToIntDef(Copy(FmtCode, 2, Length(FmtCode)), 0); Related := FindResponseByIEN(PromptIEN, AnInstance); if (Related <> nil) and ((Pos(Related.EValue, x) > 0) or (Pos(x, Related.EValue) > 0)) then Exit; end; ExcludeText := False; if (Length(x) = 0) or (CompareText(x, Omit) = 0) then Exit; FormattedText := x; if IsChild and (Length(Leading) > 0) and (CharAt(Leading, 1) <> '@') then FormattedText := Leading + ' ' + FormattedText; if IsChild and (Length(Trailing) > 0) and (CharAt(Trailing, 1) <> '@') then FormattedText := FormattedText + ' ' + Trailing; end; {with APrompt} end; function TResponses.FindPromptByIEN(AnIEN: Integer): TPrompt; var i: Integer; begin Result := nil; with FPrompts do for i := 0 to Count - 1 do with TPrompt(Items[i]) do if IEN = AnIEN then begin Result := TPrompt(Items[i]); break; end; end; procedure TResponses.AppendChildren(var ParentText: string; ChildPrompts: string; AnInstance: Integer); var x, Segment: string; Boundary, ChildIEN: Integer; ExcludeText: Boolean; AResponse: TResponse; APrompt: TPrompt; begin while Length(ChildPrompts) > 0 do begin Boundary := Pos('~', ChildPrompts); if Boundary = 0 then Boundary := Length(ChildPrompts) + 1; Segment := Copy(ChildPrompts, 1, Boundary - 1); Delete(ChildPrompts, 1, Boundary); ChildIEN := StrToIntDef(Segment, 0); APrompt := FindPromptByIEN(ChildIEN); if APrompt <> nil then begin AResponse := FindResponseByIEN(APrompt.IEN, AnInstance); if AResponse <> nil then begin FormatResponse(x, ExcludeText, APrompt, AResponse.EValue, AnInstance); //x := FormatResponse(APrompt, AResponse.EValue, AnInstance); if not ExcludeText then begin if (Length(ParentText) > 0) and (Length(x) > 0) then ParentText := ParentText + ' '; ParentText := ParentText + x; end; {if not ExcludeText} end; {if AResponse} end; {if APrompt} end; {while Length} end; {AppendChildren} function TResponses.GetOrderText: string; { loop thru the response objects and build the order text } var i, AnInstance, NumInstance: Integer; x, Segment: string; ExcludeText, StartNewline: Boolean; AResponse: TResponse; APrompt: TPrompt; begin Result := ''; with FPrompts do for i := 0 to Count - 1 do begin APrompt := TPrompt(Items[i]); if APrompt.Sequence = 0 then Continue; // skip if prompt not in formatting sequence NumInstance := 0; Segment := ''; AnInstance := NextInstance(APrompt.ID, 0); while AnInstance > 0 do begin Inc(NumInstance); AResponse := FindResponseByName(APrompt.ID, AnInstance); FormatResponse(x, ExcludeText, APrompt, AResponse.EValue, AnInstance); //x := FormatResponse(APrompt, AResponse.EValue, AnInstance); if not ExcludeText then begin if Length(APrompt.Children) > 0 then AppendChildren(x, APrompt.Children, AnInstance); if Length(x) > 0 then begin // should the newline property be checked for children, too? if APrompt.NewLine and (Length(Result) > 0) then x := CRLF + x; if NumInstance > 1 then Segment := Segment + ','; if Length(Segment) > 0 then Segment := Segment + ' '; Segment := Segment + x; end; {if Length(x)} end; {if not ExcudeText} AnInstance := NextInstance(APrompt.ID, AnInstance); end; {while AnInstance} if NumInstance > 0 then with APrompt do begin if Length(Segment) > 0 then begin if Copy(Segment, 1, 2) = CRLF then begin Segment := Copy(Segment, 3, Length(Segment)); StartNewline := True; end else StartNewline := False; if (Length(Leading) > 0) then begin if (CharAt(Leading, 1) <> '@') then Segment := Leading + ' ' + Segment else Segment := FVarLeading + ' ' + Segment; end; {if Length(Leading)} if StartNewline then Segment := CRLF + Segment; if (Length(Trailing) > 0) then begin if (CharAt(Trailing, 1) <> '@') then Segment := Segment + ' ' + Trailing else Segment := Segment + ' ' + FVarTrailing; end; {if Length(Trailing)} end; {if Length(Segment)} if Length(Result) > 0 then Result := Result + ' '; Result := Result + Segment; end; {with APrompt} end; {with FPrompts} end; {GetOrderText} procedure TResponses.Update(const APromptID: string; AnInstance: Integer; const AnIValue, AnEValue: string); { for a given Prompt,Instance update or create the associated response object } var AResponse: TResponse; begin AResponse := FindResponseByName(APromptID, AnInstance); if AResponse = nil then begin AResponse := TResponse.Create; AResponse.PromptID := APromptID; AResponse.PromptIEN := IENForPrompt(APromptID); AResponse.Instance := AnInstance; FResponseList.Add(AResponse); end; AResponse.IValue := AnIValue; AResponse.EValue := AnEValue; end; function TResponses.OrderCRC: string; const CRC_WIDTH = 8; var i: Integer; x: string; tmplst: TStringList; begin tmplst := TStringList.Create; try with FResponseList do for i := 0 to Count - 1 do with TResponse(Items[i]) do begin if IValue = TX_WPTYPE then x := EValue else x := IValue; tmplst.Add(IntToStr(PromptIEN) + U + IntToStr(Instance) + U + x); end; Result := IntToHex(CRCForStrings(tmplst), CRC_WIDTH); finally tmplst.Free; end; end; procedure TResponses.Remove(const APromptID: string; AnInstance: Integer); var AResponse: TResponse; begin AResponse := FindResponseByName(APromptID, AnInstance); if AResponse <> nil then begin FResponseList.Remove(AResponse); AResponse.Free; end; end; procedure TResponses.SaveQuickOrder(var ANewIEN: Integer; const ADisplayName: string); begin if FDisplayGroup = ClinDisp then //Clin. Meds share same quick order definition with Inpt. Meds PutQuickOrder(ANewIEN, OrderCRC, ADisplayName, InptDisp, FResponseList) else PutQuickOrder(ANewIEN, OrderCRC, ADisplayName, FDisplayGroup, FResponseList) end; procedure TResponses.SaveOrder(var AnOrder: TOrder; DlgIEN: Integer; IsIMOOrder: boolean); var ConstructOrder: TConstructOrder; i,j: integer; QOUDGroup: boolean; NewPtEvtPtr: Integer; // ptr to #100.2 APtEvtPtr: string; begin //IMOLoc := 0; NewPtEvtPtr := 0; QOUDGroup := False; if FQuickOrder > 0 then begin DlgIEN := FQuickOrder; QOUDGroup := CheckQOGroup( IntToStr(FQuickOrder) ); end; AnOrder.EditOf := FEditOrder; // null if new order, otherwise ORIFN of original order with ConstructOrder do begin if XfInToOutNow then DialogName := FDialog + '^O' else DialogName := FDialog; LeadText := FVarLeading; TrailText := FVarTrailing; DGroup := FDisplayGroup; OrderItem := DlgIEN; DelayEvent := FEventType; Specialty := FSpecialty; Effective := FEffective; LogTime := FLogTime; OCList := FOrderChecks; DigSig := DEASig; IsIMODialog := IsIMOOrder; //IMO if IsIMODialog then DGroup := ClinDisp; //AGP Change 26.35, 26.41 8518 added text order //AGP Change 26.55 remove IMO functionality for inpatient (*if (Patient.Inpatient = true) and (IsValidIMOLoc(encounter.Location,Patient.DFN)=true) and ((ConstructOrder.DialogName = 'PSJ OR PAT OE') or (ConstructOrder.DialogName = 'PSJI OR PAT FLUID OE') or (ConstructOrder.DialogName = 'OR GXTEXT WORD PROCESSING ORDE')) and ((FEditOrder = '') and (Self.FEventName = '') and (Self.FCopyOrder = '')) then begin if frmClinicWardMeds.ClinicOrWardLocation(Encounter.location) = Encounter.Location then begin ConstructOrder.IsIMODialog := True; ConstructOrder.DGroup := ClinDisp; end else IMOLoc := Patient.Location; end; *) //AGP Change 26.51, change logic to set text orders to IMO for outpatients at an outpatient location. //AGP Text orders are only treated as IMO if the order display group is a nursing display group if (Patient.Inpatient = False) and (IsValidIMOLoc(encounter.Location,Patient.DFN)=true) and (((pos('OR GXTEXT WORD PROCESSING ORDE',ConstructOrder.DialogName)>0) and (ConstructOrder.DGroup = NurDisp)) or ((ConstructOrder.DialogName = 'OR GXMISC GENERAL') and (ConstructOrder.DGroup = NurDisp)) or ((ConstructOrder.DialogName = 'OR GXTEXT TEXT ONLY ORDER') and (ConstructOrder.DGroup = NurDisp))) and //AGP Change CQ #10757 ((FEditOrder = '') and (Self.FEventName = '') and (Self.FCopyOrder = '')) then begin ConstructOrder.IsIMODialog := True; ConstructOrder.DGroup := ClinDisp; end; IsEventDefaultOR := EventDefaultOD; if IsUDGroup or QOUDGroup then begin for i := 0 to FResponseList.Count - 1 do if UpperCase(TResponse(FResponseList.Items[i]).PromptID) = 'PICKUP' then begin FResponseList.Delete(i); Break; end; end; if SaveAsCurrent then ConstructOrder.DelayEvent := #0; ResponseList := FResponseList; if (FEventIFN>0) and (EventExist(Patient.DFN, FEventIFN)>0) then begin APtEvtPtr := IntToStr(EventExist(Patient.DFN, FEventIFN)); PTEventPtr := APtEvtPtr; //PutNewOrder(AnOrder, ConstructOrder, OrderSource, IMOLoc); PutNewOrder(AnOrder, ConstructOrder, OrderSource); if not SaveAsCurrent then begin AnOrder.EventPtr := PTEventPtr; AnOrder.EventName := 'Delayed ' + MixedCase(Piece(EventInfo(APtEvtPtr),'^',4)); end; end else begin //PutNewOrder(AnOrder, ConstructOrder, OrderSource, IMOLoc); PutNewOrder(AnOrder, ConstructOrder, OrderSource); if not SaveAsCurrent then begin if (FEventIFN > 0) and (FParentEvent.ParentIFN > 0) then begin {For a child event, create a parent event in 100.2 first} SaveEvtForOrder(Patient.DFN, FParentEvent.ParentIFN, AnOrder.ID); NewPtEvtPtr := EventExist(Patient.DFN, FParentEvent.ParentIFN); AnOrder.EventPtr := IntToStr(NewPtEvtPtr); AnOrder.EventName := 'Delayed ' + MixedCase(Piece(EventInfo(IntToStr(NewPtEvtPtr)),'^',4)); {Then create the child event in 100.2} SaveEvtForOrder(Patient.DFN, FEventIFN, ''); NewPtEvtPtr := EventExist(Patient.DFN, FEventIFN); end else if (FEventIFN > 0) and (FParentEvent.ParentIFN = 0) then begin SaveEvtForOrder(Patient.DFN, FEventIFN, AnOrder.ID); NewPtEvtPtr := EventExist(Patient.DFN, FEventIFN); AnOrder.EventPtr := IntToStr(NewPtEvtPtr); AnOrder.EventName := 'Delayed ' + MixedCase(Piece(EventInfo(IntToStr(NewPtEvtPtr)),'^',4)); end; if FEventIFN > 0 then begin for j := 1 to frmOrders.lstSheets.Items.Count - 1 do begin if FEventIFN = StrToInt( Piece(Piece(frmOrders.lstSheets.Items[j],'^',1),';',1) ) then begin frmOrders.lstSheets.Items[j] := IntToStr( NewPtEvtPtr) + '^' + Piece(frmOrders.lstSheets.Items[j],'^',2); frmOrders.lstSheets.ItemIndex := j; end; end; end; end; end; DEASig := ''; //PKI end; AnOrder.EditOf := FEditOrder; {Begin BillingAware} if rpcGetBAMasterSwStatus then begin UBAGlobals.BAOrderID := ''; UBAGlobals.BAOrderID := AnOrder.ID; end; {Begin BillingAware} end; procedure TResponses.SetControl(AControl: TControl; const APromptID: string; AnInstance: Integer); { sets the value of a control, uses ID string & instance to find the right response entry } var i: Integer; AResponse: TResponse; IEN: integer; HasObjects: boolean; procedure AssignBPText(List: TStrings; const Value: string); var tmp, cptn, DocInfo: string; LType: TTemplateLinkType; begin DocInfo := ''; LType := DisplayGroupToLinkType(DisplayGroup); cptn := 'Reason for Request: ' + EValueFor('ORDERABLE', 1); tmp := Value; case LType of ltConsult: IEN := StrToIntDef(GetServiceIEN(IValueFor('ORDERABLE', 1)),0); ltProcedure: IEN := StrToIntDef(GetProcedureIEN(IValueFor('ORDERABLE', 1)),0); else IEN := 0; end; ExpandOrderObjects(tmp, HasObjects); FOrderContainsObjects := FOrderContainsObjects or HasObjects; if IEN <> 0 then begin // template will execute on copy order if commented out (tried to eliminate for CSV v22, RV) // //if (Length(tmp) > 0) and (not HasTemplateField(tmp)) then // CheckBoilerplate4Fields(tmp, cptn) //else ExecuteTemplateOrBoilerPlate(tmp, IEN, LType, nil, cptn, DocInfo); end else CheckBoilerplate4Fields(tmp, cptn); List.Text := tmp; end; begin AResponse := FindResponseByName(APromptID, AnInstance); if AResponse = nil then Exit; if AControl is TLabel then with TLabel(AControl) do Caption := AResponse.EValue else if AControl is TStaticText then with TStaticText(AControl) do Caption := AResponse.EValue else if AControl is TButton then with TButton(AControl) do Caption := AResponse.EValue else if AControl is TEdit then with TEdit(AControl) do Text := AResponse.EValue else if AControl is TMaskEdit then with TMaskEdit(AControl) do Text := AResponse.EValue else if AControl is TCheckBox then with TCheckBox(AControl) do Checked := (StrToIntDef(AResponse.IValue,0) > 0) or (UpperCase(AResponse.IValue) = 'Y') else if AControl is TMemo then with TMemo(AControl) do AssignBPText(Lines, AResponse.EValue) else if AControl is TRichEdit then with TRichEdit(AControl) do AssignBPText(Lines, AResponse.EValue) else if AControl is TORListBox then with TORListBox(AControl) do begin for i := 0 to Items.Count - 1 do if Piece(Items[i], U, 1) = AResponse.IValue then ItemIndex := i; end else if AControl is TListBox then with TListBox(AControl) do begin for i := 0 to Items.Count - 1 do if Items[i] = AResponse.EValue then ItemIndex := i; end else if AControl is TComboBox then with TComboBox(AControl) do begin for i := 0 to Items.Count - 1 do if Items[i] = AResponse.EValue then ItemIndex := i; Text := AResponse.EValue; end else if AControl is TORComboBox then with TORComboBox(AControl) do begin if LongList then InitLongList(AResponse.EValue); SelectByID(AResponse.IValue); if (not LongList) and (ItemIndex < 0) then Text := AResponse.EValue; end; end; procedure TResponses.SetEventDelay(AnEvent: TOrderDelayEvent); begin with AnEvent do if EventType in ['A','D','T','M','O'] then begin FEventIFN := EventIFN; FEventName := EventName; FEventType := EventType; FSpecialty := Specialty; FEffective := Effective; FViewName := 'Delayed ' + MixedCase(EventName); FParentEvent := TParentEvent(AnEvent.TheParent); end; end; procedure TResponses.SetPromptFormat(const APromptID, NewFormat: string); var i: Integer; begin with FPrompts do for i := 0 to Count - 1 do with TPrompt(Items[i]) do if (ID = APromptID) then FmtCode := NewFormat; end; { Private calls } procedure TfrmODBase.ClearDialogControls; var i: Integer; begin FChanging := True; for i := 0 to ControlCount - 1 do begin // need to check if control is container & clear it's children also if (Controls[i] is TLabel) or (Controls[i] is TButton) or (Controls[i] is TStaticText) then Continue; if FPreserve.IndexOf(Controls[i]) < 0 then ClearControl(Controls[i]); end; FChanging := False; ShowOrderMessage( False ); end; procedure TfrmODBase.SetDisplayGroup(Value: Integer); begin FDisplayGroup := Value; Responses.FDisplayGroup := Value; end; procedure TfrmODBase.SetFillerID(const Value: string); var x: string; begin FFillerID := Value; if AddFillerAppID(FFillerID) and OrderChecksEnabled then begin StatusText('Order Checking...'); x := OrderChecksOnDisplay(FillerID); StatusText(''); if Length(x) > 0 then InfoBox(x, TC_ORDERCHECKS, MB_OK); end; end; { Protected Calls (used by descendant forms) } procedure TfrmODBase.InitDialog; begin ClearDialogControls; Responses.Clear; FAcceptOK := False; FAbortOrder := False; end; function TfrmODBase.OrderForInpatient: Boolean; var AnEventType: Char; begin AnEventType := OrderEventTypeOnCreate; // if event type = #0, then it wasn't passed or we're not in create if AnEventType = #0 then AnEventType := Responses.FEventType; case AnEventType of 'A','O': Result := True; 'D': Result := False; 'T': begin if IsPassEvt1(FEvtID,'T') then Result := False else Result := True; end else Result := Patient.Inpatient; end; end; procedure TfrmODBase.ShowOrderMessage(Show: boolean); begin if Show then begin pnlMessage.Visible := True; pnlMessage.BringToFront; memMessage.TabStop := True; end else begin pnlMessage.Visible := False; pnlMessage.SendToBack; memMessage.TabStop := False; end; end; procedure TfrmODBase.OrderMessage(const AMessage: string); {Caller needs to set pnlMessage.TabOrder} begin memMessage.Lines.SetText(PChar(AMessage)); //begin CQ: 2640 memMessage.SelStart := 0; // Put at first character SendMessage(memMessage.Handle, WM_VSCROLL, SB_TOP, 0); //End CQ: 2640 ShowOrderMessage(ContainsVisibleChar(AMessage)); end; procedure TfrmODBase.PreserveControl(AControl: TControl); begin FPreserve.Add(AControl); end; procedure TfrmODBase.SetDialogIEN(Value: Integer); begin FDialogIEN := Value; end; procedure TfrmODBase.SetupDialog(OrderAction: Integer; const ID: string); begin FOrderAction := OrderAction; FAbortOrder := False; case OrderAction of ORDER_NEW: {nothing}; ORDER_EDIT: Responses.SetEditOrder(ID); ORDER_COPY: Responses.SetCopyOrder(ID); ORDER_QUICK: Responses.SetQuickOrderByID(ID); end; if Responses.FEventType in ['A','D','T','M','O'] then Caption := Caption + ' (Delayed ' + Responses.FEventName + ')'; // ' (Event Delayed)'; if OrderAction in [ORDER_EDIT, ORDER_COPY] then cmdQuit.Caption := 'Cancel'; end; function TfrmODBase.GetEffectiveDate: TFMDateTime; begin Result := Responses.FEffective; end; function TfrmODBase.GetKeyVariable(const Index: string): string; begin if UpperCase(Index) = 'LRFZX' then Result := Piece(FKeyVariables, U, 1) else if UpperCase(Index) = 'LRFSAMP' then Result := Piece(FKeyVariables, U, 2) else if UpperCase(Index) = 'LRFSPEC' then Result := Piece(FKeyVariables, U, 3) else if UpperCase(Index) = 'LRFDATE' then Result := Piece(FKeyVariables, U, 4) else if UpperCase(Index) = 'LRFURG' then Result := Piece(FKeyVariables, U, 5) else if UpperCase(Index) = 'LRFSCH' then Result := Piece(FKeyVariables, U, 6) else if UpperCase(Index) = 'PSJNOPC' then Result := Piece(FKeyVariables, U, 7) else if UpperCase(Index) = 'GMRCNOPD' then Result := Piece(FKeyVariables, U, 8) else if UpperCase(Index) = 'GMRCNOAT' then Result := Piece(FKeyVariables, U, 9) else if UpperCase(Index) = 'GMRCREAF' then Result := Piece(FKeyVariables, U, 10) else Result := ''; end; procedure TfrmODBase.SetKeyVariables(const VarStr: string); begin FKeyVariables := VarStr; end; procedure TfrmODBase.Validate(var AnErrMsg: string); const TX_OR_DISABLED = 'Ordering has been disabled. Press Quit.'; TX_PAST_START = 'The start date may not be earlier than the present.'; TX_NO_LOCATION = 'A location must be identified.' + CRLF + '(Select File | Update Provider/Location)'; TX_NO_PROVIDER = 'A provider who is authorized to write orders must be indentified.' + CRLF + '(Select File | Update Provider/Location)'; var StartStr,x: string; StartDt: TFMDateTime; begin AnErrMsg := ''; if User.NoOrdering then AnErrMsg := 'Ordering has been disabled. Press Quit.'; // take this out if we need to check for earlier start date/times // should this check be against FMNow?? StartStr := Piece(Responses.IValueFor('START', 1), '.', 1); if not IsFMDateTime(StartStr) then StartDt := StrToFMDateTime(StartStr) else StartDt := StrToFloat(StartStr); if (StartDt > 0) and (StartDt < FMToday) then AnErrMsg := 'The start date may not be earlier than the present.'; //frmFrame.UpdatePtInfoOnRefresh; if (not Patient.Inpatient) and (Responses.EventIFN > 0) then x := '' else begin if Encounter.Location = 0 then AnErrMsg := TX_NO_LOCATION; end; if (Encounter.Provider = 0) or (PersonHasKey(Encounter.Provider, 'PROVIDER') = False) then AnErrMsg := TX_NO_PROVIDER; if IsPFSSActive and Responses.PromptExists('VISITSTR') then Responses.Update('VISITSTR', 1, Encounter.VisitStr, Encounter.VisitStr); end; { Form Calls } procedure TfrmODBase.FormCreate(Sender: TObject); begin inherited; memOrder.Color := ReadOnlyColor; FAcceptOK := False; FAutoAccept := False; FChanging := False; FClosing := False; FFromQuit := False; FTestMode := False; FIncludeOIPI := True; FEvtForPassDischarge := #0; FCtrlInits := TCtrlInits.Create; FResponses := TResponses.Create; FPreserve := TList.Create; FIsIMO := False; //imo FIsSupply := False; {This next bit is mostly for the font size. It also sets the default size of order forms if it is not in the database. This is handy if a new user wants to have large fonts. However, in the general case, this will be resized through rMisc.SetFormPosition.} if not AutoSizeDisabled then ResizeFormToFont(self); DoSetFontSize(MainFontSize); imgMessage.Picture.Icon.Handle := LoadIcon(0, IDI_ASTERISK); //if User.NoOrdering then cmdAccept.Enabled := False; if uCore.User.NoOrdering then cmdAccept.Enabled := False; FDlgFormID := OrderFormIDOnCreate; FEvtID := OrderEventIDOnCreate; FEvtType := OrderEventTypeOnCreate; FEvtName := OrderEventNameOnCreate; end; procedure TfrmODBase.FormDestroy(Sender: TObject); begin FCtrlInits.Free; FResponses.Free; FPreserve.Free; //DestroyingOrderDialog; if Assigned(FCallOnExit) then FCallOnExit; if (Owner <> nil) and (Owner is TWinControl) then SendMessage(TWinControl(Owner).Handle, UM_DESTROY, FRefNum, 0); inherited; end; procedure TfrmODBase.FormKeyPress(Sender: TObject; var Key: Char); { causes RETURN to be treated as pressing a tab key (need to have user preference) } begin inherited; if (Key = #13) and not (ActiveControl is TCustomMemo) then begin Key := #0; Perform(WM_NEXTDLGCTL, 0, 0); end; end; { Accept & Quit Buttons } function TfrmODBase.AcceptOrderChecks: Boolean; { returns True if order was accepted with order checks, false if order should be cancelled } var StartDtTm: string; OIList: TStringList; begin Result := True; Responses.OrderChecks.Clear; if not OrderChecksEnabled then Exit; OIList := TStringList.Create; try StatusText('Order Checking...'); Responses.BuildOCItems(OIList, StartDtTm, FillerID); OrderChecksOnAccept(Responses.OrderChecks, FillerID, StartDtTm, OIList, DupORIFN); DupORIFN := ''; StatusText(''); Result := AcceptOrderWithChecks(Responses.OrderChecks); finally OIList.Free; end; end; function TfrmODBase.ValidSave: Boolean; const TX_NO_SAVE = 'This order cannot be saved for the following reason(s):' + CRLF + CRLF; TX_NO_SAVE_CAP = 'Unable to Save Order'; TX_SAVE_ERR = 'Unexpected error - it was not possible to save this order.'; var ErrMsg: string; NewOrder: TOrder; CanSign, OrderAction: Integer; //thisSourceOrder: TOrder; begin Result := True; Validate(ErrMsg); if Length(ErrMsg) > 0 then begin InfoBox(TX_NO_SAVE + ErrMsg, TX_NO_SAVE_CAP, MB_OK); Result := False; Exit; end; if not AcceptOrderChecks then begin if AskAnotherOrder(DialogIEN) then InitDialog // ClearDialogControls is in InitDialog else begin ClearDialogControls; // to allow form to close without prompting to save order Close; end; Result := False; Exit; end; if FTestMode then begin Result := False; Exit; end; // LES validation checking for changed lab order if not LESValidationCheck then Exit; NewOrder := TOrder.Create; Responses.SaveOrder(NewOrder, DialogIEN, FIsIMO); if frmOrders.IsDefaultDlg then begin frmOrders.EventDefaultOrder := NewOrder.ID; frmOrders.EvtOrderList.Add(NewOrder.EventPtr + '^' + NewOrder.ID); frmOrders.IsDefaultDlg := False; end; if Length(DfltCopay)>0 then SetDefaultCoPayToNewOrder(NewOrder.ID, DfltCopay); if (Length(FEvtName)>0) then begin NewOrder.EventName := 'Delayed ' + MixedCase(FEvtName); FEvtName := ''; end; if not ProcessOrderAcceptEventHook(NewOrder.ID, NewOrder.DGroup) then begin if NewOrder.ID <> '' then begin if (Encounter.Provider = User.DUZ) and User.CanSignOrders then CanSign := CH_SIGN_YES else CanSign := CH_SIGN_NA; if NewOrder.Signature = OSS_NOT_REQUIRE then CanSign := CH_SIGN_NA; Changes.Add(CH_ORD, NewOrder.ID, NewOrder.Text, Responses.FViewName, CanSign); UBAGlobals.TargetOrderID := NewOrder.ID; if Responses.EditOrder = '' then OrderAction := ORDER_NEW else OrderAction := ORDER_EDIT; SendMessage(Application.MainForm.Handle, UM_NEWORDER, OrderAction, Integer(NewOrder)); end else InfoBox(TX_SAVE_ERR, TX_NO_SAVE_CAP, MB_OK); end; NewOrder.Free; // free here - recieving forms should get own copy using assign end; procedure TfrmODBase.cmdAcceptClick(Sender: TObject); const TX_CMPTEVT = ' occurred since you started writing delayed orders. ' + 'The orders that were entered and signed have now been released. ' + 'Any unsigned orders will be released immediately upon signature. ' + #13#13 + 'To write new delayed orders for this event you need to click the write delayed orders button again and select the appropriate event. ' + 'Orders delayed to this same event will remain delayed until the event occurs again.' + #13#13 + 'The Orders tab will now be refreshed and switched to the Active Orders view. ' + 'If you wish to continue to write active orders for this patient, ' + 'close this message window and continue as usual.'; var theGrpName: string; alreadyClosed: boolean; begin FAcceptOK := False; CIDCOkToSave := False; alreadyClosed := False; self.Responses.Cancel := False; if frmOrders <> nil then begin if (frmOrders.TheCurrentView <> nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0) and IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN) then begin theGrpName := 'Delayed ' + frmOrders.TheCurrentView.EventDelay.EventName; SaveAsCurrent := True; end; end; if ValidSave then begin FAcceptOK := True; CIDCOkToSave := True; with Responses do if not FAutoAccept and (CopyOrder = '') and (EditOrder = '') and (TransferOrder = '') and AskAnotherOrder(DialogIEN) then InitDialog // ClearDialogControls is in InitDialog else begin ClearDialogControls; // to allow form to close without prompting to save order Close; alreadyClosed := True; end; if NoFresh then begin if SaveAsCurrent then begin SaveAsCurrent := False; with Responses do begin if not alreadyClosed then begin ClearDialogControls; Close; end; end; frmOrders.GroupChangesUpdate(theGrpName); Exit; end; end else begin if SaveAsCurrent then begin SaveAsCurrent := False; with Responses do begin if not alreadyClosed then begin ClearDialogControls; Close; end; end; frmOrders.GroupChangesUpdate(theGrpName); //EDONeedRefresh := True; Exit; end; end end; {if ValidSave} if SaveAsCurrent then SaveAsCurrent := False; end; procedure TfrmODBase.cmdQuitClick(Sender: TObject); begin inherited; Close; end; procedure TfrmODBase.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; // unlock an order that is being edited if accept wasn't pressed // this unlock is currently done in ActivateOrderDialog //with Responses do if (Length(EditOrder) > 0) and (not FAcceptOK) then UnlockOrder(EditOrder); PopKeyVars; SaveUserBounds(Self); FClosing := True; Action := caFree; (* if User.NoOrdering then Exit; if Length(memOrder.Text) > 0 then if InfoBox(TX_ACCEPT + memOrder.Text, TX_ACCEPT_CAP, MB_YESNO) = ID_YES then if not ValidSave then begin FClosing := False; Action := caNone; end; *) end; procedure TfrmODBase.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin inherited; //self.Responses.Cancel := False; if User.NoOrdering then Exit; if FAbortOrder then exit; if FOrderAction in [ORDER_EDIT, ORDER_COPY] then Exit; // don't invoke verify dialog if FOrderAction = ORDER_QUICK then Exit; // should this be here?? if frmFrame.ContextChanging then begin // close any sub-dialogs created by order dialog FIRST!! exit; end; if Length(memOrder.Text) > 0 then begin if InfoBox(TX_ACCEPT + memOrder.Text, TX_ACCEPT_CAP, MB_YESNO) = ID_YES then CanClose := ValidSave else memOrder.Text := ''; // so don't return False on subsequent CloseQuery end; end; procedure TfrmODBase.TabClose(var CanClose: Boolean); begin inherited; CanClose := True; if Length(memOrder.Text) > 0 then if InfoBox(TX_ACCEPT + memOrder.Text, TX_ACCEPT_CAP, MB_YESNO) = ID_YES then if not ValidSave then CanClose := False; if CanClose then InitDialog; end; procedure TfrmODBase.memMessageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; ShowOrderMessage( False ); end; procedure TfrmODBase.SetDefaultCoPay(AnOrderID: string); begin FDfltCopay := GetDefaultCopay(AnOrderID); end; procedure TfrmODBase.DoSetFontSize( FontSize: integer); begin if AutoSizeDisabled then ResizeAnchoredFormToFont( Self ) else begin //You get to resize the window yourself! Font.Size := FontSize; memMessage.DefAttributes.Size := FontSize; end; end; procedure TfrmODBase.SetFontSize( FontSize: integer); begin DoSetFontSize( FontSize ); end; function TResponses.GetIENForPrompt(const APromptID: string): Integer; var i: Integer; begin Result := 0; with FPrompts do for i := 0 to Count - 1 do with TPrompt(Items[i]) do if (ID = APromptID) then begin Result := IEN; break; end; end; procedure TfrmODBase.pnlMessageExit(Sender: TObject); begin inherited; ShowOrderMessage(False); end; procedure TfrmODBase.pnlMessageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; FMessageClickX := X; FMessageClickY := Y; end; procedure TfrmODBase.pnlMessageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin inherited; if (ssLeft in Shift) then pnlMessage.SetBounds(pnlMessage.Left + X - FMessageClickX, pnlMessage.Top + Y - FMessageClickY, pnlMessage.Width, pnlMessage.Height); end; function TfrmODBase.LESValidationCheck: boolean; var idx: integer; LESGrpList,LESRejectedReason: TStringList; IsLESOrder: boolean; TempMSG,LESODInfo: string; begin Result := True; if Length(Responses.EditOrder)>1 then begin LESGrpList := TStringList.Create; PiecesToList(GetDispGroupForLES,'^',LESGrpList); IsLESOrder := False; for idx:=0 to LESGrpList.Count - 1 do if StrToIntDef(LESGrpList[idx],0) = Responses.DisplayGroup then begin IsLESOrder := True; Break; end; if IsLESOrder then begin TempMSG := ''; LESODInfo := Patient.DFN + '^' + Responses.IValueFor('ORDERABLE',1) + '^' + IntToStr(Encounter.Location) + '^' + IntToStr(Encounter.Provider) + '^' + Responses.IValueFor('START',1); LESRejectedReason := TStringList.Create; LESValidationForChangedLabOrder(LESRejectedReason,LESODInfo); if LESRejectedReason.Count > 0 then begin for idx := 0 to LESRejectedReason.Count - 1 do begin if Length(LESRejectedReason[idx])>0 then TempMSG := TempMSG + #13 + LESRejectedReason[idx]; end; if Length(TempMSG)>0 then begin ShowMessage(TempMSG); Result := False; end; end; end; end; end; end.