LOOKUPSSN^TMGDFN

90 views
Skip to first unread message

Ivan Metzlar

unread,
Jan 6, 2015, 3:45:51 PM1/6/15
to hard...@googlegroups.com
LOOKUPSSN^TMGDFN suddenly stopped working.

N PHN S PHN="BC9123123123"
N RET S RET=$$SSNLOOKUP^TMGGDFN(PHN)
ZWRITE RET
RET=0

A patient with this SSN exists, is there an index that needs to be updated? How?

Cheers,

Ivan

David Whitten

unread,
Jan 6, 2015, 4:12:43 PM1/6/15
to Hard Hats Mailing List
Why do you think "BC9123123123" is a valid SSN ?

Unless you changed your Data Dictionary, that will not pass
the input transform for File #2, Field #0.09 that I have.

^DD(2,.09,0)="SOCIAL SECURITY NUMBER^FXa^^0;9^K:X[""""""""!($A(X)=45)
X I $D(X) S:'$D(DPTX) DFN=DA D SSN^DGINP Q I $L(X)>10"

As to LOOKUPSSN^TMGDFN or $$SSNLOOKUP^TMGGDFN (which is it ?)
I haven't seen this code, and will defer to Kevin Toppenberg for what indexes
it may or may not depend upon.
> --
> --
> http://groups.google.com/group/Hardhats
> To unsubscribe, send email to Hardhats+u...@googlegroups.com
>
> ---
> You received this message because you are subscribed to the Google Groups
> "Hardhats" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to hardhats+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ivan Metzlar

unread,
Jan 6, 2015, 4:22:29 PM1/6/15
to hard...@googlegroups.com
Hi David,

it is $$SSNLOOKUP^TMGGDFN sorry for the confusion.

I did change the field. The maximum length is 30 and the input transform I have is

K:X[""""!($A(X)=45) X I $D(X) S:'$D(DPTX
) DFN=DA D:'(($G(DA)="+")&(X["P")) SSN^DGRPDD1 Q

And I commented the line in DGRPDD1.m at SSN+4

; G SSNQ:X["P" I X'?9N K X Q

Cheers,

Ivan Metzlar

unread,
Jan 6, 2015, 4:40:00 PM1/6/15
to hard...@googlegroups.com
David's question pointed me to the index rebuild from the Fileman console D Q^DI

After I rebuild the SSN index the following works:

D DT^DICRW
S DUZ(2)=1
N RET S RET=$$SSNLOOKUP^TMGGDFN(PHN)
zwrite RET
RET=865

Cheers,

Kevin Toppenberg

unread,
Jan 6, 2015, 6:14:36 PM1/6/15
to hard...@googlegroups.com
Ivan,

Glad my routine is working for you.  

You said you commented this line out...

; G SSNQ:X["P" I X'?9N K X Q

If you do this, then you will not be able to enter "pseudo" SSN's.  Is that your intention?  Also, this line was trying to do some protection of the database from invalid inputs.  Are you sure you want to do that?  You show this number: BC9123123123.  Is this typical format of the values you can accept (i.e. 'BC' followed by 10 numbers)?  If so, why not change the line to something like this:

GOTO SSNQ:X["P" 
IF X'?1"B"1"C"10N KILL X QUIT

Kevin

Ivan Metzlar

unread,
Jan 9, 2015, 4:09:33 PM1/9/15
to hard...@googlegroups.com
Hi Kevin,

thanks for the tips. Yes the care numbers in Canada are different per province so we decided on making the field free form prefixed with the province abbreviation so for British Columbia it could be BC1234567890 and for Manitoba MB665544

Your routine worked fine but I ended up using the index directly so to find the IEN by care number I do:

S PHN="MB665544"
S IEN=$O(^DPT("SSN",PHN,0))

I guess I am slowly learning some FileMan essentials or is this bad practice?

Cheers,

Ivan

Kevin Toppenberg

unread,
Jan 9, 2015, 6:27:34 PM1/9/15
to hard...@googlegroups.com
Ivan,

What you are doing is directly accessing the globals, as compared to going through Fileman services.  My understanding is that this is generally felt to be OK in the case of READING, but not when WRITING data.  So your code looks OK to me.

Kevin

Ivan Metzlar

unread,
Jan 12, 2015, 5:12:28 PM1/12/15
to hard...@googlegroups.com
Thanks Kevin!

Do you have any idea why my code here https://github.com/metzlar/vistacan/blob/master/Mumps/ZVCA.m does not store the visit problem (in a way for CPRS to know) ?

Kevin Toppenberg

unread,
Jan 13, 2015, 7:14:25 AM1/13/15
to hard...@googlegroups.com
Ivan,

I have not worked with that API so I don't know right off why your code doesn't work.  But here are some thoughts:  One of the debugging tools I use is to capture the parameters passed during a call that works, and then compare them to what I am doing. 

For example, you make this call: MAKE^TIUSRVP(.NIEN,DFN,TITLE,VDT,VLOC,VSIT,.TIUX,VSTR,SUPPRESS,NOASF) 

I would wedge some code on the first line after the tag MAKE in the module TIUSRVP as follows:
NEW ZZDEBUG SET ZZDEBUG=0
IF ZZDEBUG=0 DO
. MERGE ^TMP("IVAN",$J,NIEN)=NIEN
. MERGE ^TMP("IVAN",$J,DFN)=DFN
. MERGE ^TMP("IVAN",$J,TITLE)=TITLE
. MERGE ^TMP("IVAN",$J,VDT)=VDT
. MERGE ^TMP("IVAN",$J,VLOC)=VLOC
. MERGE ^TMP("IVAN",$J,VSIT)=VSIT
. MERGE ^TMP("IVAN",$J,TIUX)=TIUX
. MERGE ^TMP("IVAN",$J,VSTR)=VSTR
. MERGE ^TMP("IVAN",$J,SUPPRESS)=SUPPRESS
. MERGE ^TMP("IVAN",$J,NOASF)=NOASF
ELSE  DO
. KILL NIEN,DFN,TITLE,VDT,VLOC,VSIT,TIUX,VSTR,SUPPRESS,NOASF
. MERGE NIEN=^TMP("IVAN",$J,NIEN)
. MERGE DFN=^TMP("IVAN",$J,DFN)
. MERGE TITLE=^TMP("IVAN",$J,TITLE)
. MERGE VDT=^TMP("IVAN",$J,VDT)
. MERGE VLOC=^TMP("IVAN",$J,VLOC)
. MERGE VSIT=^TMP("IVAN",$J,VSIT)
. MERGE TIUX=^TMP("IVAN",$J,TIUX)
. MERGE VSTR=^TMP("IVAN",$J,VSTR)
. MERGE SUPPRESS=^TMP("IVAN",$J,SUPPRESS)
. MERGE NOASF=^TMP("IVAN",$J,NOASF)

This code will store the input parameters to a global location that you can inspect.  So run CPRS and create a visit normally.  Then inspect the global and see what you got.  Then run your code and again inspect what you got and compare the two.  Also, this code can be stepped through using your favorite debugger.  Right after the line where ZZDEBUG is set to 0, change it to 1, and then the code will load up the saved parameters.  You can step through the code with real life values.

One other thing, your labels, e.g. CREATEVISITWNOTE,  are longer than 8 characters.  GT.M allows this, but I think it violates SACC.  When I first started with mumps, I hated the VA's SACC regulations.  I figured I was not in the VA and thus didn't need to follow them.  So I widely used MixedCase variable names etc.  But I found that others didn't want to use my code because it didn't pass the XINDEX code verifier.  So now I am having to slowly go back and refactor my code without somehow introducing bugs.    So if I was coding your function, and wanted to keep good, descriptive code, I would use this name, but put a comment on the line describing what it does:

CRVSTWNT(PRV,DFN,DIA,CONTENT) ; CREATE VISIT W NOTE

Overall, I dislike this way of doing things because the other places in the code where your API are called are not immediately readable.  But it is the compromise I have come to.

Last thing, I can't remember if we talked about this on another thread, but do you have a debugger that lets you step through code?  I can show you how to use the TMG debugger sometime if you want.

Kevin

Kevin Toppenberg

unread,
Jan 13, 2015, 7:57:12 AM1/13/15
to hard...@googlegroups.com
I just read the code and realized I didn't write what I meant.  

. MERGE ^TMP("IVAN",$J,NIEN)=NIEN

should be

. MERGE ^TMP("IVAN",$J,"NIEN")=NIEN

I.e. in the global reference, the NAME of the variable should be used as a node, not the VALUE of the variable.  And this for each of the variables stored.

Kevin

Steven McPhelan

unread,
Jan 15, 2015, 11:04:03 AM1/15/15
to hardhats
Kevin, I would dispute your statement, "...My understanding is that this is generally felt to be OK in the case of READING..."

Today, hardware is cheap.  Human intervention is expensive.  It was not that way when VistA started.  VistA still has much code that originated in those early days.  So seeing examples of VA VistA coding style does not necessarily condone that coding style today.

Today, one should get adequate hardware to enable the applications to use the DBMS system versus directly accessing the internals of the file.  Thus one should always use FileMan DBMS tools to READ, WRITE, and DELETE to the VistA database unless one has a valid reason in today's world not to.  The argument that It is easier to access the global directly is a poor and unacceptable excuse.  Perhaps a better example for accessing the database files directly might be doing a file or files conversion.  Using the Fileman tool for 10,000s or millions of records to find the records to be converted is probably unreasonable.  However, updating the record should still be done through FM APIs in most cases to ensure that file's integrity.  The point is that the decision should be well considered in each and every case where one decides to read the global files directly.

Steve

"Any man who thinks he can be happy and prosperous by letting the government take care of him; better take a closer look at the American Indian." - Henry Ford

Steven McPhelan

unread,
Jan 15, 2015, 11:06:23 AM1/15/15
to hardhats
I should have added, Remember for a response to this group one literally has the whole world listening.

Steve

"Any man who thinks he can be happy and prosperous by letting the government take care of him; better take a closer look at the American Indian." - Henry Ford

Kevin Toppenberg

unread,
Jan 15, 2015, 4:08:09 PM1/15/15
to hard...@googlegroups.com
Coding styles are always domains ripe for contention.   I would be curious as to the CPU multiplier needed to convert every direct global read into a Fileman call.  I suspect it would be somewhere between 10x and 100x.  The SACC does allow direct global reads, correct?

Kevin

Mike Henderson

unread,
Jan 15, 2015, 4:34:24 PM1/15/15
to hard...@googlegroups.com
Kevin and all, while direct global reads are not absolutely forbidden, it should be kept in mind that as VistA continues to evolve and interoperability walls (one hopes) continue to fall, there will be an increasing number of polymorphous objects -- such as patient demographic and identifying attributes -- that will defy easy ultra-efficient global sets and gets.  The trade-off, long term, will be between relatively CPU-costly DBS calls and relatively more efficient custom setters and getters as in, for example, Java.

Mike Henderson, FHL7
Director, Open Source Product Management
OSEHRA (Open Source Electronic Health Record Alliance)
900 N. Glebe Road, Suite 4-016, Arlington, VA 22203 USA

Ivan Metzlar

unread,
Jan 16, 2015, 4:51:26 PM1/16/15
to hard...@googlegroups.com
Thank you all for your help. To me - being a long time Java/JavaSript/Python programmer - it seems for a language like Mumps coding styles must be strictly enforced to keep code maintainable and readable (and working, with the global scope and all). I disagree with label name lengths of 8 that sounds like a rule from the past. label names as well as variable names should be descriptive and human readable. A maximum length of 8 might not be readable at all. Here is a nice write up http://en.wikipedia.org/wiki/Naming_convention_(programming) 

Kevin Toppenberg

unread,
Jan 16, 2015, 5:02:30 PM1/16/15
to hard...@googlegroups.com
The good thing about running your own system is that you can do whatever you want.  :-)

Kevin

David Whitten

unread,
Jan 16, 2015, 8:11:48 PM1/16/15
to Hard Hats Mailing List
And the reality about running a shared system is that you have to
share with other people.
Even if you want to name things the way you want, you have to do it in
a way that doesn't
take away other people's choices too.

I personally agree that only eight (8) uppercase characters is very
limiting. I also think that
the circumstances where those limits are necessary have evaporated
over the years.

To my knowledge the relevant part of the SAC
( http://www.va.gov/TRM/files/SACC_2008.pdf ) is:

2.2.4 Routine names and labels are limited to eight (8) characters
(not including the formal list for parameter passing) and may not
contain lower case characters.

The suggested change (in 2014) was:
-> Routine names and labels are limited to thirty one (31) characters
and MAY contain mixed upper and lower case characters

I don't know the current status for these 2014 changes .

Steven McPhelan

unread,
Jan 23, 2015, 4:11:58 PM1/23/15
to hardhats
I just saw an addendum to the SACC from 6/4/2014.  This topic has been discussed many a time.  I was on the losing side, I preferred that the first line reflect the date the routine was lasted edited.

Routine First Line clarification 6/4/2014

 

Question: My understanding is that the Date on routine line 1 is the routine creation date and this date should never be edited when editing the routine for subsequent patches.   Others that I work with think that this date should be edited to reflect the date/time most recently edited (i.e. date of the most recent patch edit).

 

Which is correct?

 

Response:

2.2.1   The first line of a routine must be in the following format:

 

routine name<ls>; site/programmer<space>-<space>brief description [optional space];date of last edit [update not required, time is optional].

 

We feel that, for now, the site/programmer entry should not be changed. You may add a comment line after the third line to document any development done and the name and location of the developer.


This statement is also ambiguous.  The standard only calls for specify the format of the first two lines.  So why would this addendum specifically state to insert comments after the THIRD line?

Andy Bruce

unread,
Jan 23, 2015, 4:40:19 PM1/23/15
to hard...@googlegroups.com

TIn a recent IOM publication (2011-Health IT and Patient Safety) the VA was credited with pioneering the development of Healthcare Failure Modes and Effects Analysis (HFMEA) which was apparently trademarked for use with barcode and medication administration). The VA also developed 2 complimentary reporting systems ... the external NASA/VA Patient Safety Reporting System and the internal VA National Center for Patient Safety reporting system. Does anyone know anything about these reporting systems...use and/or their availability?
I saw the recent BCMA post but was unaware adverse event reporting was so well developed.
Thanks,
HAB

Reply all
Reply to author
Forward
0 new messages