Requirement Constraints

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Wednesday, 28 August 2013

HL7 Parsing–My Own Parser

Posted on 11:37 by Unknown

In my previous post, i showed how to use HAPI for parsing HL7 File. But for my current assignment , i am not able to go further on HAPI. Here is my requirement

1. I need to parse Patient lab result ORU^R01 Message type
2. Here is the structure of the message

MSH
PID
ORC
IN1
IN2...IN4
DG1....DG4
OBR (N times, under each OBR, there can be N number of OBXs)
----> OBX1....OBXn
----------NTEs(Some time OBX may also contain NTEs
NTE(Some times, OBR may not have OBX, but they have NTEs

3. And here is the challenge, upfront i will not know how many DG, OBR and under each OBR, how many OBXs are present in the result file. So without any looping mechanism, we cannot parse the file and convert into human readable text.
4. I tried with lot with HAPI to achieve the desired result, but no luck. May be because of the following reasons
            a) HAPI Does not have much examples to show the power of the parser of each Message type
            b) I do not have time to read their API and form the example Smile

            c) Finally HAPI does not have ability to parse the multiple OBR and OBX


So i decided to drop HAPI and started my own parser. I have been working in Health care industry for more than 14 years, so understanding the terminology/domain is not a problem for me. Writing our own parser is fun for me, because i have the done the same thing in VB6 successfully.  But this time with java. Here is the detail code.

package hl7.parse;

import java.util.HashMap;
import java.util.Map;

public class MyParser {

String message;
private Long totalLines = (long) 0;
private Long MSHCount = (long) 0;
private Long PIDCount = (long) 0;
private Long ORCCount = (long) 0;
private Long totalDGs = (long) 0;
private Long OBRCounter = (long) 0;
private Long OBXCounter = (long) 0;
private String MSH;
private String PID;
private String ORC;
private Map<String, String> element = new HashMap<String, String>();
private String currentOBR;

public Long getTotalDGs() {
return totalDGs;
}

public Long getTotalOBRs() {
return OBRCounter;
}

public Long getORCCount() {
return ORCCount;
}

public String getORC() {
return ORC;
}

public String getMSH() {
return MSH;
}

public String getPID() {
return PID;
}

public Long getPIDCount() {
return PIDCount;
}

public Long getMSHCount() {
return MSHCount;
}

public Long getTotalLines() {
return totalLines;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public MyParser(String message) {
this.message = message;
}

public String getValue(String key) {
return element.get(key);
}

public void parseIt() {
String delimiter = "\\r";
String[] temp;
temp = message.split(delimiter);
for (int i = 0; i < temp.length; i++) {
// Store the lines if developer wants it
element.put("Segment-" + i, temp[i]);
parseSegment(temp[i]);
totalLines++;
}

// Write the final one
// Store the total OBX Count -- OBR[1]OBX-count
if (this.currentOBR != null) {
String key = "OBR[" + OBRCounter + "]" + "OBX-count";
element.put(key, String.valueOf(OBXCounter));

}
}

private void parseSegment(String line) {
String segment;
segment = line.substring(0, 3);
if (segment.equalsIgnoreCase("MSH"))
parseMSH(line);

if (segment.equalsIgnoreCase("PID"))
parsePID(line);

if (segment.equalsIgnoreCase("ORC"))
parseORC(line);

if (segment.equalsIgnoreCase("DG1") || segment.equalsIgnoreCase("DG2")
|| segment.equalsIgnoreCase("DG3")
|| segment.equalsIgnoreCase("DG4"))
parseDGs(line);

if (segment.equalsIgnoreCase("OBR"))
parseOBRs(line);

if (segment.equalsIgnoreCase("OBX"))
parseOBXs(line);

}

private void parseDGs(String line) {

String delimiter = "\\|";
String[] temp;
temp = line.split(delimiter);
totalDGs++;
element.put("DG-" + totalDGs, line);
element.put("DG-" + totalDGs + "-count", String.valueOf(temp.length));
for (int i = 0; i < temp.length; i++) {
element.put("DG[" + totalDGs + "]-" + i, temp[i]);
}

}

private void parseOBRs(String line) {

String delimiter = "\\|";
String[] temp;
temp = line.split(delimiter);

// Store the total OBX Count -- OBR[1]OBX-count
if (this.currentOBR != null) {
String key = "OBR[" + OBRCounter + "]" + "OBX-count";
element.put(key, String.valueOf(OBXCounter));
}
OBRCounter++;
element.put("OBR[" + OBRCounter + "]", line);
element.put("OBR[" + OBRCounter + "]" + "-count",
String.valueOf(temp.length));
this.currentOBR = "OBR[" + OBRCounter + "]";
// Reset the OBX counter
OBXCounter = (long) 0;
for (int i = 0; i < temp.length; i++) {
element.put("OBR[" + OBRCounter + "]-" + i, temp[i]);
if (i == 4 || i == 16) //
{
parseSubComponent(temp[i], "OBR[" + OBRCounter + "]-" + i);
}
}

}

private void parseOBXs(String line) {

// Here we need to carefull, OBX are under OBR, so we need to attach to
// the correct OBR
String delimiter = "\\|";
String[] temp;
String key;
temp = line.split(delimiter);
OBXCounter++;
key = this.currentOBR + "OBX[" + OBXCounter + "]";
// Very first thing is, We need to Print the OBX Line under OBR as
// OBR[1]OBX[1]
element.put(key, line);
// OBR[1]OBX[1]-count
element.put(key + "-count", String.valueOf(temp.length));
// OBR[1]OBX[1]-1, // OBR[1]OBX[1]-2,etc
for (int i = 0; i < temp.length; i++) {
element.put(key + "-" + i, temp[i]);
}
}

private void parseMSH(String line) {

String delimiter = "\\|";
String[] temp;
temp = line.split(delimiter);
this.MSH = line;
for (int i = 0; i < temp.length; i++) {
element.put("MSH-" + i, temp[i]);
MSHCount++;
}

}

private void parseORC(String line) {

String delimiter = "\\|";
String[] temp;
temp = line.split(delimiter);
this.ORC = line;
for (int i = 0; i < temp.length; i++) {
element.put("ORC-" + i, temp[i]);
if (i == 12 || i == 17 || i == 18) //
{
parseSubComponent(temp[i], "ORC-" + i);
}
ORCCount++;
}

}

private void parsePID(String line) {

String delimiter = "\\|";
String[] temp;
temp = line.split(delimiter);
this.PID = line;
for (int i = 0; i < temp.length; i++) {

element.put("PID-" + i, temp[i]);
if (i == 5 || i == 11) // Let us parse patient Name
{
parseSubComponent(temp[i], "PID-" + i);
}
PIDCount++;
}

}

private void parseSubComponent(String line, String mapKey) {

String delimiter = "\\^";
String[] temp;
temp = line.split(delimiter);
int j;
for (int i = 0; i < temp.length; i++) {
j = i + 1;
element.put(mapKey + "-" + j, temp[i]);
}

}

}





public void onParse() {
String element;
String value;
String hl7Message = getStringFromInputStream("c:\\temp\\example1.hl7");
System.out.println("HL7 Content is " + hl7Message);
myParser = new MyParser(hl7Message);
myParser.parseIt();

element = "Receiving Facility";
value = myParser.getValue("MSH-5");
System.out.println(element + " : " + value);

element = "Patient No";
value = myParser.getValue("PID-2");
System.out.println(element + " : " + value);

element = "Lab Accession Number";
value = myParser.getValue("PID-4");
System.out.println(element + " : " + value);

element = "Patient Last Name";
value = myParser.getValue("PID-5-1");
System.out.println(element + " : " + value);

element = "Patient First Name";
value = myParser.getValue("PID-5-2");
System.out.println(element + " : " + value);

element = "Patient Middle Name";
value = myParser.getValue("PID-5-3");
System.out.println(element + " : " + value);

element = "Patient DOB";
value = myParser.getValue("PID-7");
System.out.println(element + " : " + value);

element = "Patient Sex";
value = myParser.getValue("PID-8");
System.out.println(element + " : " + value);

element = "Provider NPI";
value = myParser.getValue("ORC-12-1");
System.out.println(element + " : " + value);

element = "Provider Last Name";
value = myParser.getValue("ORC-12-2");
System.out.println(element + " : " + value);

element = "Provider First Name";
value = myParser.getValue("ORC-12-3");
System.out.println(element + " : " + value);

element = "Provider Initial";
value = myParser.getValue("ORC-12-5");
System.out.println(element + " : " + value);

element = "Account No";
value = myParser.getValue("ORC-17-1");
System.out.println(element + " : " + value);

element = "Account Name";
value = myParser.getValue("ORC-17-2");
System.out.println(element + " : " + value);

element = "Account Address";
value = myParser.getValue("ORC-18-1");
System.out.println(element + " : " + value);

element = "Account City";
value = myParser.getValue("ORC-18-2");
System.out.println(element + " : " + value);

element = "Account State";
value = myParser.getValue("ORC-18-3");
System.out.println(element + " : " + value);

element = "Account Zip";
value = myParser.getValue("ORC-18-4");
System.out.println(element + " : " + value);

element = "Account Phone";
value = myParser.getValue("ORC-18-5");
System.out.println(element + " : " + value);

System.out
.println("*********************************ALL ABOUT MSH ***********************");
// Let us print the MSH Values
for (int i = 0; i < myParser.getMSHCount(); i++) {
System.out.println("MSH-" + i + ": "
+ myParser.getValue("MSH-" + i));
}

// Ofcouse If you want to you get particular value also as follows
System.out.println("Please give me MSH[3] "
+ myParser.getValue("MSH-3"));

// Ofcourse You can also print MSH String
System.out.println("Please give me MSH Line..." + myParser.getMSH());

System.out
.println("*********************************ALL ABOUT PID ***********************");
// Ofcouse If you want to you get particular value also as follows
System.out.println("Please give me PID[3] "
+ myParser.getValue("PID-3"));

// Ofcourse You can also print PID String
System.out.println("Please give me PID Line..." + myParser.getPID());

// Component 1 [ST] family name (last name)
// Component 2 [ST] given name (first name)
// Component 3 [ST] middle initial or name
// Component 4 [ST] suffix (jr, sr, etc)
// Component 5 [ST] prefix (Mr, Mrs, Dr etc)
// Component 6 [ST] degree (MD, PHD etc)
// Component 7 [ID] name type code

// Ofcouse You can print Patient Last Name as follows
System.out.println("Please give me Patient Last Name "
+ myParser.getValue("PID-5-1"));

// Ofcouse You can print Patient First Name as follows
System.out.println("Please give me Patient First Name "
+ myParser.getValue("PID-5-2"));

// Ofcouse You can print Patient Address as follows
System.out.println("Please give me Patient Address "
+ myParser.getValue("PID-11-1"));

// Ofcouse You can print Patient Address as follows
System.out.println("Please give me Patient City "
+ myParser.getValue("PID-11-2"));

// Ofcouse You can print Patient Address as follows
System.out.println("Please give me Patient State "
+ myParser.getValue("PID-11-3"));

// Ofcouse You can print Patient Address as follows
System.out.println("Please give me Patient Zip "
+ myParser.getValue("PID-11-4"));

// Let us print the PID Values
for (int i = 0; i < myParser.getPIDCount(); i++) {
System.out.println("PID-" + i + ": "
+ myParser.getValue("PID-" + i));
}

System.out
.println("*********************************ALL ABOUT ORC***********************");
// Let us print the ORC Values
for (int i = 0; i < myParser.getORCCount(); i++) {
System.out.println("ORC-" + i + ": "
+ myParser.getValue("ORC-" + i));
}
// Ofcouse If you want to you get particular value also as follows
System.out.println("Please give me ORC[2] "
+ myParser.getValue("ORC-2"));

// Ofcourse You can also print ORC String
System.out.println("Please give me ORC Line..." + myParser.getORC());

System.out
.println("*********************************ALL ABOUT DG***********************");
// Total Number of DGs
System.out.println("Please give me Total DGs " + myParser.getTotalDGs());
// Let us print the DGs
for (int i = 1; i <= myParser.getTotalDGs(); i++) {
System.out.println("DG-" + i + ": " + myParser.getValue("DG-" + i));
}

for (int i = 1; i <= myParser.getTotalDGs(); i++) {
int total = Integer.parseInt(myParser
.getValue("DG-" + i + "-count"));
for (int j = 1; j < total; j++) {
System.out.println("DG[" + i + "]-" + j + " : "
+ myParser.getValue("DG[" + i + "]-" + j));
}

}

System.out
.println("*********************************ALL ABOUT OBR***********************");
// Total Number of OBRs
System.out.println("Please give me Total OBR " + myParser.getTotalOBRs());
// Let us print the OBRs
String key;
for (int i = 1; i <= myParser.getTotalOBRs(); i++) {
key = "OBR[" + i + "]";
System.out.println(key + " : " + myParser.getValue(key));
// We can also retieve the total elements in each OBR
System.out.println("Total Elements in " + key + " is "
+ myParser.getValue(key + "-count"));
}

for (int i = 1; i <= myParser.getTotalOBRs(); i++) {
key = "OBR[" + i + "]-count";
int total = Integer.parseInt(myParser.getValue(key));
for (int j = 1; j < total; j++) {
key = "OBR[" + i + "]-" + j;
System.out.println(key + " : " + myParser.getValue(key));
}

}

System.out
.println("*********************************ALL ABOUT OBX***********************");

key = "OBR[1]OBX-count";
// For given OBR, You can find how many OBXs are there as follows
System.out.println("Please give me Total OBXs in OBR[1] "
+ myParser.getValue(key));

key = "OBR[2]OBX-count";
System.out.println("Please give me Total OBXs in OBR[2] "
+ myParser.getValue(key));

key = "OBR[1]OBX[1]";
// You can also Print the OBX Line in each OBR as follows
System.out.println("Please give me OBX[1] in OBR[1] " + myParser.getValue(key));
key = "OBR[1]OBX-count";
int total = Integer.parseInt(myParser.getValue(key));

// You can also Print all OBXs in OBR[1]
for (int i = 1; i <= total; i++) {
key = "OBR[1]OBX[" + i + "]";
System.out.println("OBR[1]OBX[" + i + "] => " + myParser.getValue(key));
}

// Dont know how many OBRs and how many OBXs in each OBRs, no problem,
// we can put them in the loop
for (int i = 1; i <= myParser.getTotalOBRs(); i++) {
key = "OBR[" + i + "]";
System.out.println(key + " : " + myParser.getValue(key));
key = key + "OBX-count";
total = Integer.parseInt(myParser.getValue(key));
for (int j = 1; j <= total; j++) {
key = "OBR[" + i + "]" + "OBX[" + j + "]";
System.out.println("----->" + key + " : " + myParser.getValue(key));
}
}
}

// convert InputStream to String
private static String getStringFromInputStream(String fileName) {

BufferedReader br = null;
StringBuilder sb = new StringBuilder();

String line;
try {
br = new BufferedReader(new FileReader(fileName));
while ((line = br.readLine()) != null) {
sb.append(line + "\r");
}

} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

return sb.toString();

}

Sample HL7 File


MSH|^~\&|mas|MY XXXX LAB|mas|100|201303201430||ORU^R01||P|2.3|
PID|1|K2TE154871|^^^MRN~^^^CID~^^^ACCN|234567892|K2^TEST^||19640512|M|||^^FL^|||||U|||||||0||
ORC|1|000133423|||CM||||201206132103|PHH|201206141230|^^^^     ^^^^^|||||261^XXXX CARE CENTER|31231 IN.STATE ROAD 17 SUITE 102^LAUDERHILL^NY^22313^95455848444|3|PHH|
IN1|1|09102|MCARE|MEDICARE PART B|PO BOX 44117^^JACKSONVILLE^FL^322310018||8664549007||MEDICARE PART B|||||||K2^TEST^|01|00000000|^^NY^||||||||||||||||||||||||||||T|
DG1|1|ICD|319|UNSPECIFIED MENTAL RETARDATION|||||||||||||BUIR154337^000039106|
DG2|1|ICD|30490|UNSPECIFIED DRUG DEPENDENCE, UNSPECIFIED USE|||||||||||||HOJA159610^000039110|
OBR|1|234567892||22014^K2S|||201211151512|201211151514||||||201211151512||^^^^     ^^^^^||A|GENERAL CHEMISTRY||||||X|
OBX|1|TX|22014^K2S|  ^A^A|X||-||||X||9|201211150000||...||
OBR|2|234567892||2521S^K2S|||201211151512|201211181214|||A|||201211151512||^^^^     ^^^^^||D|DRUGS||||||F|
OBX|1|TX|2521S^K2S|  ^A^A|NEGATIVE|CUTOFF 20 ng/ml|-||||F||9|201211181214||MAM||
OBR|3|234567892||4814^GABA|||201211151512|201212061207|||A|||201211151512||^^^^     ^^^^^||D|DRUGS||||||C|
OBX|1|TX|4814^GABA|  ^D^D|X||-||||X||9|201212060949||RBJ|MERCY^^^^^^|
NTE|1|LD|     A THERAPEUTIC RANGE FOR GABAPENTIN HAS NOT BEEN ESTABLISHED. THE RANGE OF|
NTE|2|LD|     THE ASSAY IS 0.75 TO 40.00 ug/mL.REPORTABLE RESULT BELOW THIS RANGE IS|
NTE|3|LD|     <0.75 ug/mL AND ABOVE THIS RANGE IS >40.0 ug/ml.|
OBR|4|234567892||9632^GABA|||201211151512|201211191214|||A|||201211151512||^^^^     ^^^^^||A|GENERAL CHEMISTRY||||||X|
OBX|1|TX|9632^GABA|  ^A^A|X|ng/ml|NEGATIVE-|*|||X||9|201211191214||MAM||



Here is the output

Receiving Facility : 100
Patient No : K2TE154871
Lab Accession Number : 234567892
Patient Last Name : K2
Patient First Name : TEST
Patient Middle Name : null
Patient DOB : 19640512
Patient Sex : M
Provider NPI :
Provider Last Name :
Provider First Name :
Provider Initial :
Account No : 261
Account Name : XXXX CARE CENTER
Account Address : 31231 IN.STATE ROAD 17 SUITE 102
Account City : LAUDERHILL
Account State : NY
Account Zip : 22313
Account Phone : 95455848444
*********************************ALL ABOUT MSH ***********************
MSH-0: MSH
MSH-1: ^~\&
MSH-2: mas
MSH-3: MY XXXX LAB
MSH-4: mas
MSH-5: 100
MSH-6: 201303201430
MSH-7:
MSH-8: ORU^R01
MSH-9:
MSH-10: P
MSH-11: 2.3
Please give me MSH[3] MY XXXX LAB
Please give me MSH Line...MSH|^~\&|mas|MY XXXX LAB|mas|100|201303201430||ORU^R01||P|2.3|
*********************************ALL ABOUT PID ***********************
Please give me PID[3] ^^^MRN~^^^CID~^^^ACCN
Please give me PID Line...PID|1|K2TE154871|^^^MRN~^^^CID~^^^ACCN|234567892|K2^TEST^||19640512|M|||^^FL^|||||U|||||||0||
Please give me Patient Last Name K2
Please give me Patient First Name TEST
Please give me Patient Address
Please give me Patient City
Please give me Patient State FL
Please give me Patient Zip null
PID-0: PID
PID-1: 1
PID-2: K2TE154871
PID-3: ^^^MRN~^^^CID~^^^ACCN
PID-4: 234567892
PID-5: K2^TEST^
PID-6:
PID-7: 19640512
PID-8: M
PID-9:
PID-10:
PID-11: ^^FL^
PID-12:
PID-13:
PID-14:
PID-15:
PID-16: U
PID-17:
PID-18:
PID-19:
PID-20:
PID-21:
PID-22:
PID-23: 0
*********************************ALL ABOUT ORC***********************
ORC-0: ORC
ORC-1: 1
ORC-2: 000133423
ORC-3:
ORC-4:
ORC-5: CM
ORC-6:
ORC-7:
ORC-8:
ORC-9: 201206132103
ORC-10: PHH
ORC-11: 201206141230
ORC-12: ^^^^ ^^^^^
ORC-13:
ORC-14:
ORC-15:
ORC-16:
ORC-17: 261^XXXX CARE CENTER
ORC-18: 31231 IN.STATE ROAD 17 SUITE 102^LAUDERHILL^NY^22313^95455848444
ORC-19: 3
ORC-20: PHH
Please give me ORC[2] 000133423
Please give me ORC Line...ORC|1|000133423|||CM||||201206132103|PHH|201206141230|^^^^ ^^^^^|||||261^XXXX CARE CENTER|31231 IN.STATE ROAD 17 SUITE 102^LAUDERHILL^NY^22313^95455848444|3|PHH|
*********************************ALL ABOUT DG***********************
Please give me Total DGs 2
DG-1: DG1|1|ICD|319|UNSPECIFIED MENTAL RETARDATION|||||||||||||BUIR154337^000039106|
DG-2: DG1|1|ICD|30490|UNSPECIFIED DRUG DEPENDENCE, UNSPECIFIED USE|||||||||||||HOJA159610^000039110|
DG[1]-1 : 1
DG[1]-2 : ICD
DG[1]-3 : 319
DG[1]-4 : UNSPECIFIED MENTAL RETARDATION
DG[1]-5 :
DG[1]-6 :
DG[1]-7 :
DG[1]-8 :
DG[1]-9 :
DG[1]-10 :
DG[1]-11 :
DG[1]-12 :
DG[1]-13 :
DG[1]-14 :
DG[1]-15 :
DG[1]-16 :
DG[1]-17 : BUIR154337^000039106
DG[2]-1 : 1
DG[2]-2 : ICD
DG[2]-3 : 30490
DG[2]-4 : UNSPECIFIED DRUG DEPENDENCE, UNSPECIFIED USE
DG[2]-5 :
DG[2]-6 :
DG[2]-7 :
DG[2]-8 :
DG[2]-9 :
DG[2]-10 :
DG[2]-11 :
DG[2]-12 :
DG[2]-13 :
DG[2]-14 :
DG[2]-15 :
DG[2]-16 :
DG[2]-17 : HOJA159610^000039110
*********************************ALL ABOUT OBR***********************
Please give me Total OBR 4
OBR[1] : OBR|1|234567892||22014^K2S|||201211151512|201211151514||||||201211151512||^^^^ ^^^^^||A|GENERAL CHEMISTRY||||||X|
Total Elements in OBR[1] is 26
OBR[2] : OBR|2|234567892||2521S^K2S|||201211151512|201211181214|||A|||201211151512||^^^^ ^^^^^||D|DRUGS||||||F|
Total Elements in OBR[2] is 26
OBR[3] : OBR|3|234567892||4814^GABA|||201211151512|201212061207|||A|||201211151512||^^^^ ^^^^^||D|DRUGS||||||C|
Total Elements in OBR[3] is 26
OBR[4] : OBR|4|234567892||9632^GABA|||201211151512|201211191214|||A|||201211151512||^^^^ ^^^^^||A|GENERAL CHEMISTRY||||||X|
Total Elements in OBR[4] is 26
OBR[1]-1 : 1
OBR[1]-2 : 234567892
OBR[1]-3 :
OBR[1]-4 : 22014^K2S
OBR[1]-5 :
OBR[1]-6 :
OBR[1]-7 : 201211151512
OBR[1]-8 : 201211151514
OBR[1]-9 :
OBR[1]-10 :
OBR[1]-11 :
OBR[1]-12 :
OBR[1]-13 :
OBR[1]-14 : 201211151512
OBR[1]-15 :
OBR[1]-16 : ^^^^ ^^^^^
OBR[1]-17 :
OBR[1]-18 : A
OBR[1]-19 : GENERAL CHEMISTRY
OBR[1]-20 :
OBR[1]-21 :
OBR[1]-22 :
OBR[1]-23 :
OBR[1]-24 :
OBR[1]-25 : X
OBR[2]-1 : 2
OBR[2]-2 : 234567892
OBR[2]-3 :
OBR[2]-4 : 2521S^K2S
OBR[2]-5 :
OBR[2]-6 :
OBR[2]-7 : 201211151512
OBR[2]-8 : 201211181214
OBR[2]-9 :
OBR[2]-10 :
OBR[2]-11 : A
OBR[2]-12 :
OBR[2]-13 :
OBR[2]-14 : 201211151512
OBR[2]-15 :
OBR[2]-16 : ^^^^ ^^^^^
OBR[2]-17 :
OBR[2]-18 : D
OBR[2]-19 : DRUGS
OBR[2]-20 :
OBR[2]-21 :
OBR[2]-22 :
OBR[2]-23 :
OBR[2]-24 :
OBR[2]-25 : F
OBR[3]-1 : 3
OBR[3]-2 : 234567892
OBR[3]-3 :
OBR[3]-4 : 4814^GABA
OBR[3]-5 :
OBR[3]-6 :
OBR[3]-7 : 201211151512
OBR[3]-8 : 201212061207
OBR[3]-9 :
OBR[3]-10 :
OBR[3]-11 : A
OBR[3]-12 :
OBR[3]-13 :
OBR[3]-14 : 201211151512
OBR[3]-15 :
OBR[3]-16 : ^^^^ ^^^^^
OBR[3]-17 :
OBR[3]-18 : D
OBR[3]-19 : DRUGS
OBR[3]-20 :
OBR[3]-21 :
OBR[3]-22 :
OBR[3]-23 :
OBR[3]-24 :
OBR[3]-25 : C
OBR[4]-1 : 4
OBR[4]-2 : 234567892
OBR[4]-3 :
OBR[4]-4 : 9632^GABA
OBR[4]-5 :
OBR[4]-6 :
OBR[4]-7 : 201211151512
OBR[4]-8 : 201211191214
OBR[4]-9 :
OBR[4]-10 :
OBR[4]-11 : A
OBR[4]-12 :
OBR[4]-13 :
OBR[4]-14 : 201211151512
OBR[4]-15 :
OBR[4]-16 : ^^^^ ^^^^^
OBR[4]-17 :
OBR[4]-18 : A
OBR[4]-19 : GENERAL CHEMISTRY
OBR[4]-20 :
OBR[4]-21 :
OBR[4]-22 :
OBR[4]-23 :
OBR[4]-24 :
OBR[4]-25 : X
*********************************ALL ABOUT OBX***********************
Please give me Total OBXs in OBR[1] 1
Please give me Total OBXs in OBR[2] 1
Please give me OBX[1] in OBR[1] OBX|1|TX|22014^K2S| ^A^A|X||-||||X||9|201211150000||...||
OBR[1]OBX[1] => OBX|1|TX|22014^K2S| ^A^A|X||-||||X||9|201211150000||...||
OBR[1] : OBR|1|234567892||22014^K2S|||201211151512|201211151514||||||201211151512||^^^^ ^^^^^||A|GENERAL CHEMISTRY||||||X|
----->OBR[1]OBX[1] : OBX|1|TX|22014^K2S| ^A^A|X||-||||X||9|201211150000||...||
OBR[2] : OBR|2|234567892||2521S^K2S|||201211151512|201211181214|||A|||201211151512||^^^^ ^^^^^||D|DRUGS||||||F|
----->OBR[2]OBX[1] : OBX|1|TX|2521S^K2S| ^A^A|NEGATIVE|CUTOFF 20 ng/ml|-||||F||9|201211181214||MAM||
OBR[3] : OBR|3|234567892||4814^GABA|||201211151512|201212061207|||A|||201211151512||^^^^ ^^^^^||D|DRUGS||||||C|
----->OBR[3]OBX[1] : OBX|1|TX|4814^GABA| ^D^D|X||-||||X||9|201212060949||RBJ|MERCY^^^^^^|
OBR[4] : OBR|4|234567892||9632^GABA|||201211151512|201211191214|||A|||201211151512||^^^^ ^^^^^||A|GENERAL CHEMISTRY||||||X|
----->OBR[4]OBX[1] : OBX|1|TX|9632^GABA| ^A^A|X|ng/ml|NEGATIVE-|*|||X||9|201211191214||MAM||

Read More
Posted in EMR Labs Stuff | No comments

Friday, 23 August 2013

ZK Dropupload example

Posted on 04:21 by Unknown
This is another example for ZK Drag and Drop files in the zul. Apart from the official example, i have shown how to add muliple files and store in the DB and also, if browser does not support HTML 5, then user can still use button to upload their files.

image

ChosenboxViewModel.java

package demo.combobox.chosenbox;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.zkoss.bind.BindContext;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.io.Files;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;

import demo.data.EmailLabels;

public class ChosenboxViewModel {

private ListModelList<String> contactsModel = new ListModelList<String>();
private ListModel<String> labelsModel = new ListModelList<String>(
EmailLabels.getLabels());
private List<String> filesList = new ArrayList<String>();



public List<String> getFilesList() {
return filesList;
}

public void setFilesList(List<String> filesList) {
this.filesList = filesList;
}

@Init
public void init() {

}

@Command("newContact")
public void newContact(@BindingParam("contact") String contact) {
contactsModel.add(contact);
contactsModel.addToSelection(contact);
}

public ListModel<String> getContactsModel() {
return contactsModel;
}

public ListModel<String> getLabelsModel() {
return labelsModel;
}

@Command
@NotifyChange("filesList")
public void doUpload(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) throws IOException {

UploadEvent upEvent = null;
Object objUploadEvent = ctx.getTriggerEvent();
if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
upEvent = (UploadEvent) objUploadEvent;
}
if (upEvent != null) {
org.zkoss.util.media.Media[] medias = upEvent.getMedias();
String pathToStore = getDestinationFolder();
for (org.zkoss.util.media.Media m : medias) {
filesList.add(m.getName());
Files.copy(new File(pathToStore + m.getName()),
m.getStreamData());
}

}
}

private String getDestinationFolder() {

String returnPath = null;
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH); // Note: zero based!
int day = now.get(Calendar.DAY_OF_MONTH);
returnPath = Executions.getCurrent().getDesktop().getWebApp()
.getRealPath("/");
String yearPath = "\\" + "myFiles" + "\\" + year + "\\" + month + "\\"
+ day + "\\";
returnPath = returnPath + yearPath;
File baseDir = new File(returnPath);
if (!baseDir.exists()) {
baseDir.mkdirs();
}
return returnPath;
}

@Command
@NotifyChange("filesList")
public void onDelete(@BindingParam("currentFile") String curFile)
{
filesList.remove(curFile);
}
}


EmailContacts.java


package demo.data;

import java.util.Arrays;
import java.util.Collection;

public class EmailContacts {

public static Collection<? extends String> getContacts() {
return Arrays.asList("Adam (adam@company.org)",
"Chris (chris@company.org)", "Daniel (daniel@company.org)",
"Eve(eve@company.org)", "Fritz (fritz@company.org)",
"Mary (mary@company.org)", "Max (max@company.org)",
"John (john@company.org)", "Peter (peter@company.org)");
}

}

EmailLabels.java


package demo.data;

import java.util.Arrays;
import java.util.Collection;

public class EmailLabels {

public static Collection<? extends String> getLabels() {
return Arrays.asList("accounts", "friends", "information", "personal",
"products", "projects", "support", "work");
}

}



chosenbox.zul


<zk>
<style src="/widgets/combobox/chosenbox/style.css" />
<vlayout hflex="1" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('demo.combobox.chosenbox.ChosenboxViewModel')">
<image sclass="maillogo"
src="/widgets/combobox/chosenbox/img/logo_zkmail.png" />
<vlayout sclass="mail" hflex="1">
<hbox sclass="mailformrow" hflex="1" align="center">
<label sclass="maillabel" value="Label">To</label>
<chosenbox sclass="mailinput" hflex="1"
model="@load(vm.contactsModel)"
emptyMessage="type or select contacts (existing or new ones)"
creatable="true" createMessage="Create new contact '{0}'"
onSearch="@command('newContact', contact=event.value)"
open="false" />
</hbox>
<hbox sclass="mailformrow" hflex="1" align="center">
<label sclass="maillabel" value="Label"></label>
<chosenbox sclass="mailinput" hflex="1"
model="@load(vm.labelsModel)"
emptyMessage="choose one or more labels" />
</hbox>
<textbox id="hereplease" sclass="mailinput" multiline="true"
hflex="1" height="100px">
</textbox>
</vlayout>
<window title="Attachment(s) You can drage and Drop here"
id="attachwin" border="normal" height="1 80%" width="50%">
<vlayout>
<hlayout>
<dropupload maxsize="5120" detection="self"
width="570px" height="30px"
onUpload="@command('doUpload',upEvent=event)"
content="Drop the files here">
</dropupload>
<button upload="true,maxsize=5120"
onUpload="@command('doUpload',upEvent=event)" label="Add Files">
</button>

</hlayout>
<listbox height="200px" id=""
model="@load(vm.filesList)">
<listhead sizable="true">
<listheader label="FileName" />
<listheader label="Delete" />
</listhead>
<template name="model">
<listitem>
<listcell label="@bind(each)" />
<listcell>
<button image="DeleteRecord.png"
onClick="@command('onDelete', currentFile=each)" />
</listcell>
</listitem>
</template>
</listbox>
</vlayout>
</window>
</vlayout>


</zk>





ChosenboxViewModel.java


package demo.combobox.chosenbox;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.zkoss.bind.BindContext;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.io.Files;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;

import demo.data.EmailLabels;

public class ChosenboxViewModel {

private ListModelList<String> contactsModel = new ListModelList<String>();
private ListModel<String> labelsModel = new ListModelList<String>(
EmailLabels.getLabels());
private List<String> filesList = new ArrayList<String>();



public List<String> getFilesList() {
return filesList;
}

public void setFilesList(List<String> filesList) {
this.filesList = filesList;
}

@Init
public void init() {

}

@Command("newContact")
public void newContact(@BindingParam("contact") String contact) {
contactsModel.add(contact);
contactsModel.addToSelection(contact);
}

public ListModel<String> getContactsModel() {
return contactsModel;
}

public ListModel<String> getLabelsModel() {
return labelsModel;
}

@Command
@NotifyChange("filesList")
public void doUpload(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) throws IOException {

UploadEvent upEvent = null;
Object objUploadEvent = ctx.getTriggerEvent();
if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
upEvent = (UploadEvent) objUploadEvent;
}
if (upEvent != null) {
org.zkoss.util.media.Media[] medias = upEvent.getMedias();
String pathToStore = getDestinationFolder();
for (org.zkoss.util.media.Media m : medias) {
filesList.add(m.getName());
Files.copy(new File(pathToStore + m.getName()),
m.getStreamData());
}

}
}

private String getDestinationFolder() {

String returnPath = null;
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH); // Note: zero based!
int day = now.get(Calendar.DAY_OF_MONTH);
returnPath = Executions.getCurrent().getDesktop().getWebApp()
.getRealPath("/");
String yearPath = "\\" + "myFiles" + "\\" + year + "\\" + month + "\\"
+ day + "\\";
returnPath = returnPath + yearPath;
File baseDir = new File(returnPath);
if (!baseDir.exists()) {
baseDir.mkdirs();
}
return returnPath;
}

@Command
@NotifyChange("filesList")
public void onDelete(@BindingParam("currentFile") String curFile)
{
filesList.remove(curFile);
}
}

Read More
Posted in ZK MVVM | No comments

Thursday, 22 August 2013

Hibernate Custom validator to validate Multiple email ids

Posted on 13:02 by Unknown
In my current project, i need to validate email ids where user will be enter more email id in one text area with semicolon as separator. Before storing into DB, i need to check whether all the email ids are valid one. So i decided to create custom Hibernate validator constraint. For more examples and understanding, please check here

package com.hibernate;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = ValidateEmailValidator.class)
@Documented
public @interface ValidateEmails {

String message() default "{default message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

}



package com.hibernate;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class ValidateEmailValidator implements
ConstraintValidator<ValidateEmails, String> {

String emailPattern = ".+@.+\\.[a-z]+";
private final Pattern EMAIL_PATTERN = Pattern.compile(emailPattern);

@Override
public void initialize(ValidateEmails arg0) {

}

@Override
public boolean isValid(String value,
ConstraintValidatorContext constraintContext) {
if (value == null) {
return true;
}
boolean isValid = true;
String delimiter = ";";
String[] temp;
temp = value.split(delimiter);
for (int i = 0; i < temp.length; i++) {
if (validateEmail(temp[i]) == false) {
return false;
}
}
return isValid;
}

private boolean validateEmail(String email) {

return validatePattern(email, EMAIL_PATTERN);
}

private boolean validatePattern(String toBeValidated, Pattern pattern) {
if (toBeValidated == null)
return false;
Matcher m = pattern.matcher(toBeValidated);
return m.matches();
}
}


Example Usage:

@ValidateEmails(message = "Some email ids are invalid for Send result to email.")
private String resultEmails;

Read More
Posted in Hibernate Validator | No comments

ZK List box inline Editing with Add New and Delete action

Posted on 10:33 by Unknown
In my previous example, i showed how to add New record and delete existing record in the inline Editing of grid. This one is same as previous, but i have used ZK List box. Only zul file has been changed, rest all the same code.

<zk>
<style>
.z-label { display:block; } tr.z-row td.z-row-inner { padding:
2px 5px; } .z-row-cnt, .z-column-cnt { text-align: center; }

</style>
<div apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('demo.grid.inline_editing.InlineEditingViewModel')">
<separator></separator>
<separator></separator>
<button onClick="@command('onAddNew')" label="Add New" />
<separator></separator>
<listbox id="demoGrid"
model="@load(vm.allBooks) @template((vm.displayEdit and each.editingStatus) ? 'editable' : 'noneditable')">
<listhead sizable="true">
<listheader label="Title" />
<listheader label="Author" />
<listheader visible="@load(vm.displayEdit)" />
<listheader visible="@load(vm.displayEdit)" />
</listhead>
<template name="editable">
<listitem>
<listcell>
<textbox cols="60" id="titletext"
value="@load(each.title) @save(each.title, before='confirm')" />
</listcell>
<listcell>
<textbox
value="@load(each.author) @save(each.author, before='confirm')" />
</listcell>
<listcell>
<div>
<button image="pencil-small.png"
onClick="@command('confirm', currentBook=each)" />
<button image="cross-small.png"
onClick="@command('changeEditableStatus', currentBook=each )" />
</div>
</listcell>
</listitem>
</template>
<template name="noneditable">
<listitem>
<listcell>
<label value="@load(each.title)" />
</listcell>
<listcell>
<label value="@load(each.author)" />
</listcell>
<listcell>
<button image="pencil-small.png"
onClick="@command('changeEditableStatus', currentBook=each )" />
</listcell>
<listcell>
<button image="DeleteRecord.png"
onClick="@command('onDelete', currentBook=each )" />
</listcell>
</listitem>
</template>
</listbox>
</div>
</zk>
Read More
Posted in | No comments

ZK Example for inline Editing with Add New and Delete

Posted on 08:35 by Unknown

I am quite impressed on this demo from ZK. But adding new record and delete existing record is missing as part of typical CRUD. So i thought that we can add that and see how it works. So here is the example on that

image
ZK Version : 6.5.2

Book.java

package demo.grid.inline_editing;

public class Book {
private String author, title ;
private boolean editingStatus;

public Book(String author, String title, boolean editingStatus) {
this.author = author;
this.title = title;
this.editingStatus = editingStatus;

}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}


public boolean getEditingStatus() {
return editingStatus;
}

public void setEditingStatus(boolean editingStatus) {
this.editingStatus = editingStatus;
}

}


BookData.java



package demo.grid.inline_editing;

import java.util.ArrayList;
import java.util.List;

public class BookData {

private final List<Book> allBooks = new ArrayList<Book>();

public BookData(){
allBooks.add(new Book("Philip Hensher", "The Fit",false ));
allBooks.add(new Book("Philip Hensher", "Kitchen Venom",false));
allBooks.add(new Book("Michael Greenberg", "Hurry Down Sunshine",false));
allBooks.add(new Book("Michael Greenberg", "Painless Vocabulary",false));
allBooks.add(new Book("Rick Perlstein", "Nixonland: The Rise of a President and the Fracturing",false));
allBooks.add(new Book("Rick Perlstein", "Nixonland",false));
}

public List<Book> getAllBooks() {
return allBooks;
}

}

Zul File

<zk>
<style>
.z-label { display:block; } tr.z-row td.z-row-inner { padding:
2px 5px; } .z-row-cnt, .z-column-cnt { text-align: center; }

</style>
<div apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('demo.grid.inline_editing.InlineEditingViewModel')">
<separator></separator>
<separator></separator>
<button onClick="@command('onAddNew')" label="Add New" />
<separator></separator>
<grid id="demoGrid"
model="@load(vm.allBooks) @template((vm.displayEdit and each.editingStatus) ? 'editable' : 'noneditable')">
<columns>
<column width="350px">Title</column>
<column width="650px">Author</column>
<column width="120px" visible="@load(vm.displayEdit)">
Edit
</column>
<column width="120px" visible="@load(vm.displayEdit)">
Delete
</column>
</columns>
<template name="editable">
<row>
<textbox cols="60" id="titletext"
value="@load(each.title) @save(each.title, before='confirm')" />
<textbox
value="@load(each.author) @save(each.author, before='confirm')" />

<div>
<button image="pencil-small.png"
onClick="@command('confirm', currentBook=each)" />
<button image="cross-small.png"
onClick="@command('changeEditableStatus', currentBook=each )" />
</div>
</row>
</template>
<template name="noneditable">
<row>
<label value="@load(each.title)" />
<label value="@load(each.author)" />
<button image="pencil-small.png"
onClick="@command('changeEditableStatus', currentBook=each )" />
<button image="DeleteRecord.png"
onClick="@command('onDelete', currentBook=each )" />
</row>
</template>
</grid>
</div>
</zk>





View Model

package demo.grid.inline_editing;

import java.util.List;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zhtml.Messagebox;

public class InlineEditingViewModel {

private BookData data = new BookData();

private boolean displayEdit = true;
private boolean isAddNew = false;

public boolean isDisplayEdit() {
return displayEdit;
}

@NotifyChange({ "allBooks", "displayEdit" })
public void setDisplayEdit(boolean displayEdit) {
this.displayEdit = displayEdit;
}

public List<Book> getAllBooks() {
return data.getAllBooks();
}

@Command
public void changeEditableStatus(@BindingParam("currentBook") Book book) {
if (isAddNew == true) {
data.getAllBooks().remove(book);
isAddNew = false;
} else
book.setEditingStatus(!book.getEditingStatus());
refreshRowTemplate(book);

}

@Command
public void confirm(@BindingParam("currentBook") Book book) {
if (isAddNew == true) {
if (book.getAuthor().equalsIgnoreCase("")
|| book.getTitle().equalsIgnoreCase("")) {
Messagebox.show(" Please enter the values");
return;
} else
isAddNew = false;
}
book.setEditingStatus(!book.getEditingStatus());
refreshRowTemplate(book);
}

public void refreshRowTemplate(Book lcs) {
/*
* This code is special and notifies ZK that the bean's value has
* changed as it is used in the template mechanism. This stops the
* entire Grid's data from being refreshed
*/
BindUtils.postNotifyChange(null, null, lcs, "editingStatus");
}

@Command
@NotifyChange({ "allBooks", "displayEdit" })
public void onAddNew() {
data.getAllBooks().add(0, new Book("", "", true));
isAddNew = true;
}

@Command
@NotifyChange({ "allBooks", "displayEdit" })
public void onDelete(@BindingParam("currentBook") Book book)
{
data.getAllBooks().remove(book);
}
}


Output :
image

Video Demo
http://screencast.com/t/Lwe5GJkN3fQa


You can download the Source here

Read More
Posted in ZK Framework | No comments

Patient Demographics and Patient cases

Posted on 02:00 by Unknown

1



2


3


4


5


6



7

Read More
Posted in | No comments

Wednesday, 21 August 2013

How to get Current Date and Time and store in the bean

Posted on 21:18 by Unknown

In some cases, we always want to show the current date and time while adding new order or item, etc in the screen. Here is an example for the same.

Assume that you have the Hibernate POJO as follows

	import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Temporal(TemporalType.DATE)
private Date collectedDate;

private Time collectedTime;


public Date getCollectedDate() {
return collectedDate;
}

public void setCollectedDate(Date collectedDate) {
this.collectedDate = collectedDate;
}

public Time getCollectedTime() {
return collectedTime;
}

public void setCollectedTime(Time collectedTime) {
this.collectedTime = collectedTime;
}

Now you can use the following statement to set current date and time

this.selectedOrder.setCollectedDate(new Date());
        this.selectedOrder.setCollectedTime(new java.sql.Time(System
                .currentTimeMillis()));

Read More
Posted in Java | No comments

Friday, 16 August 2013

Maintaining Patient Insurance

Posted on 00:56 by Unknown

How patient insurances are maintained  in the EMR/PMS software's ?

Today, software's are maintaining the patient insurance in difference ways. Each method has its own cons and pros. I will list those methods which i found in my past experience.

Before getting into detail, let us see the terms "Primary",  Secondary, Tertiary and 4th Insurance". In some software, instead of calling 4th Insurance, they will call as Quaternary Insurance.

Actually, there is no defined process or method to identify which is patient primary insurance , and which is patient secondary insurance, and so on. For more details, please download this article and you will know how it has been identified. Since there is no defined way, most of the time, reception people will enter the secondary insurance information into primary and vice versa. That's the reason, all the software's providing swapping option for the insurance

And also, we should know how secondary insurance billed and get paid. Please download this document to know more on that.

Now let us see how software's are maintaining the patient insurance.

Method 1:
Maintain 2 or 4 insurance at the Patient Level

Here you can always maintain 2 or 4 insurance at active state. Give important to the word "Active" here. But, HIPAA EDI 837 Transaction allow up to  11 insurance.  So what happens, at one point of time, the existing insurance get expired and patient got new insurance ? Well, you cannot remove  that insurance from the system it because it is tightly linked to Billing (Claims) Module. So only the option is to de activate the existing primary insurance and add new insurance in the active state as primary Insurance.

The advantages in this method is : Insurance are maintained only at one place i.e. at the patient level. So any changes done here, it will impact all the claims linked to that.  This might be useful when there is error in the data entry and after the correction, they want to re submit all the claims linked to that insurance.

And also, at one point of time, there will be huge number in the inactive state, and no idea which claims are linked to that.

But what happen, if the patient is coming for two different visit types : For example, you may have a patient that is being treated for injuries sustained   from an auto accident that is covered under one insurance policy; yet that same patient may receive treatment during the same visit for a condition    unrelated to the auto accident where a different policy may be billed. So in this case, you need to maintain two primary insurance dependent on the visit type.In the above method, it is not possible, so that is one of the disadvantage.


Method : 2

Another way is to clone the patient demographics insurance while claim is created and therein after maintain the copy of all insurance at the claim  level. 
 
In this method, initially, the insurance are maintained at the patient level. But when the claim is created, software will take a copy of all insurance and will maintain along with part of the claim details. So here, after the claim is created, the insurance at the patient level is plugged off and will not have tightly linked with the claim. If any error in the policy details, of course, first we should correct at the claim level and then at the patient level for error free future claims.

if the patient is coming for two different visit types, then we can easily handle here because, we need to change only at the claim level.

Method 3:

And final method is patient case. This method not only to maintain the insurance, but it can also provide a template kind of stuff to create same  kind of claim data for the same patient again  and again to save the time.

In order understand, simply you can think patient case is nothing but to maintain group of insurances.  Let us see detail now.

What will be in the patient case. ?

1. Patient case is by patient
2. Software allows to create N number of patient cases for each patient.
3. The following details will be maintained at the patient case

  • Referring Physician
  • ICDs and CPTs
  • Insurance (Here you can define upto 11 Insurance)
  • Insurance Authorization information for each insurance if available
  • ICDs and CPTs
  • For hospital type of visits, maintain different dates such as admitted date, discharge date, accident date, etc..

Creating individual cases for why a patient is being seen by a provider simplifies the selection of insurance policies and the order in  which two or more insurance plans may be billed for various types of treatment and conditions. For example, you may have a patient that is being    treated for injuries sustained from an auto accident that is covered under one insurance policy; yet that same patient may receive treatment during   the same visit for a condition unrelated to the auto accident where a different policy may be billed.
 
Creating individual cases for patient treatment also simplifies how paperwork and claims are processed when a case involves an attorney lien or    Workers' Comp claim. For example, you could have an existing patient that has been previously seen for an illness; and later sustains an injury at his    place of employment that may involve a worker's comp claim. How claims are handled for each of these two cases is quite different. In a situation like    this, you would simply locate the existing patient record; and then create a new case for that patient that covers treatment for his injury.

In this method, we can maintain different set of primary, secondary, etc. depending upon the visit types. And also, collecting insurance from the patient is handled by the front desk people and creating the claim for the visit handled by the back office people. So there is no idea for the billing people which insurance has to select on the claim, because they may not aware what is the purpose of the visit.

If we maintain case, then it is job of the front desk to select the case at the appointment level or at the check in level. Then this will be helpful for the billing team to generate the claim for the insurance for the selected case and send to the insurance company.

Happy Insurance Maintaining !!!!!!

Welcome to the Most challenging part of the Medical Billing !!!!

Interested to see some sample screen shots for Patient case ? Here you go.

        

Questions or feedback are always welcome. You can email me at vbsenthilinnet@gmail.com. You can hire me as consultant for EMR/PMS Domain and Web development on EMR/PMS Product!
Read More
Posted in | No comments

Sunday, 11 August 2013

EDI Transactions

Posted on 09:17 by Unknown

The HIPAA transactions and code set standards are rules that standardize the electronic exchange of health-related administrative information, such as claims forms. The rules are based on electronic data interchange (EDI) standards, which allow for the exchange of information from computer-to-computer without human involvement.

A "transaction" is an electronic business document. Under HIPAA, a handful of standardized transactions will replace hundreds of proprietary, non-standard transactions currently in use. For example, the HCFA 1500 claims form/file will be replaced by the X12 837 claim/encounter transaction. Each of the HIPAA standard transactions has a name, a number, and a business or administrative use. Those of importance in a medical practice are listed in the table below.


Transaction

Number

Business use

Claim/encounter

X12 837

For submitting claim to health plan, insurer, or other payer

Eligibility inquiry and response

X12 270 and 271

For inquiring of a health plan the status of a patient.s eligibility for benefits and details regarding the types of services covered, and for receiving information in response from the health plan or payer.

Claim status inquiry and response

X12 276 and 277

For inquiring about and monitoring outstanding claims (where is the claim? Why haven.t you paid us?) and for receiving information in response from the health plan or payer. Claims status codes are now standardized for all payers.

Referrals and prior authorizations

X12 278

For obtaining referrals and authorizations accurately and quickly, and for receiving prior authorization responses from the payer or utilization management organization (UMO) used by a payer.

Health care payment and remittance advice

X12 835

For replacing paper EOB/EOPs and explaining all adjustment data from payers. Also, permits auto-posting of payments to accounts receivable system.

Health claims attachments (proposed)

X12 275

For sending detailed clinical information in support of claims, in response to payment denials, and other similar uses.



How EDI Works

Doctor diagnosis the patient and provide the treatment for the identified disease. Billing Team prepare the bill(claim) and the claim is transmitted into an EDI Document format called as 837 Health care claim. Then the EDI 837 Document securely transmitted to the insurance company via clearing house.

Then the Insurance company processes the claim which comes in the electronic format and provide the necessary reimbursement for the provider for the treatment given to the patient.

Why You Need EDI – the Benefits

  • Lower costs
  • Higher efficiency
  • Improved accuracy
  • Enhanced security
  • Greater management information

Interest to see some sample EDI Documents. Please check here.

        

Questions or feedback are always welcome. You can email me at vbsenthilinnet@gmail.com. You can hire me as consultant for EMR/PMS Domain and Web development on EMR/PMS Product!
Read More
Posted in | No comments

Friday, 9 August 2013

Health care Coding system

Posted on 04:13 by Unknown
There are different coding system used in Healthcare industry. Let us see one by one now. Let us again recall our first definition as follows

"Medical Billing is a Process of Submission of Bills/Claims to the Insurance Company in a specified format for the service rendered (for the treatment given) by the doctor for the patient."

Pay more attention to the word "treatment given by the doctor to the patient". How that information passed to the insurance company ? in plain text via email ? in audio file ? ???

The information passed by means of coding system called Current Procedural Terminology (CPT), simply by numbers, so that other end (insurance company) easily understand what the doctor did for the patient.

Say for example, For example, if you cut your finger and the doctor repairs the cut(treatment) , there is a procedure code(CPT) to put on the bill/claim to collect the payment from the insurance company. So what is that number ? The number is 12001. Search in the Google with "CPT Code 12001" for more stories/articles/information on that :).

Ok, Next who is defining all these numbers ? Well procedure codes owned, copyrighted and developed by the American Medical Association
(http://www.ama-assn.org/ama).  Next question ? AMA also define the price (reimbursement amount) for each procedure ? Yes. But that
is a another big story in healthcare about price(charges) for each procedure code. We will see later about that.

Basically there are three types of CPT which as classified as Category 1 , Category II and category III.
Category I codes include surgery, Anaesthesiology, Vaccines, etc.
Category II is used for performance measurement. Say for an example, if you are smoker, and if the doctor gives counselling to stop smoking,then that is also treated as treatment and identify by the procedure number 0002F .
Category III codes represent temporary codes for new diseases.

HCPCS Codes

HCPCS (HCFA Common Procedural Coding System) is a series of codes developed by the federal government and specifically the Center for Medicare and Medicaid Services (CMS) (formerly known as the Health Care Finance Administration (HCFA)). CMS uses these codes primarily for Medicare and Medicaid to describe procedures or items not listed in the CPT manual

What is the difference between CPT codes and HCPCS?'
CPT codes are owned and copyrighted by the American Medical Association. They describe common procedures used in the course of health care delivery and are oriented to physician use in one way or another. HCPCS are codes generated by the federal government to describe procedures that have special significance to either the Medicaid or Medicare programs.


International classification of diseases (ICD)

ICD is developed and copyrighted by the World Health Organization. ICD is a set of 3, or 5 digit codes that convert a disease, an injury
or a history of a medical condition to a number or numbers. For example, Chicken Pox or Varicella has an ICD-9 code of 052.9. We use numbers so computers can recognize them quickly because insurance companies process millions of claims daily. The 9 means the 9th revision being used. Soon ICD-9 will be eliminated due to being out-dated and because there are so many current codes that there will no longer be any room for new codes. ICD-9 will be replaced by ICD-10. Every year, in October, the codes are released and are effective. There are new codes, codes with different descriptions, and codes that are eliminated. Why do we have new codes? New diseases and injuries are identified every day.

Most commonly used ICD Codes

ICD Code

Description

789

Abdominal Pain

538.8

Stomach Disorder – Acid Reflux

305

ALCOHOL ABUSE

477.9

ALLERGIC RHINITIS CAUSE UNSPECIFIED

308.9

UNSPECIFIED ACUTE REACTION TO STRESS

401.9

UNSPECIFIED ESSENTIAL HYPERTENSION

796.2

BLOOD PRESSURE

787.91

Diarrhea

250.00

Diabetes

786.2

Cough

460

Common Cold

786.5

Chest Pain

723.1

Neck Pain

346.1

Migraine

782.4

Jaundice

783.2

Weight Loss

339.00

Cluster headache syndrome, unspecified

339.10

Tension-type headache, unspecified

780.5

Sleep Disturbance

571.90

Liver disease - chronic, unspecified

493.90

Asthma, unspecified


Relationship between an ICD and a CPT code

CPT codes describe what you do, and ICD codes describe why you do it.


The critical relationship between an ICD-9 code and a CPT code is that the diagnosis supports the medical necessity of the procedure. Since both ICD-9 and CPT are numeric codes, health care consulting firms, the government, and insurers have all designed software that compares the codes for a logical relationship. For example, a bill for CPT 31256, nasal/sinus endoscopy would not be supported by ICD-9 826.0, closed fracture of a phalanges of the foot. Such a claim would be quickly identified and rejected.

Each service you provide becomes a line item (a CPT code) on an insurance claim form. Although your level of reimbursement is linked to a claim's CPT codes, you need to record a symptom, diagnosis or complaint (an ICD-9 code) to establish the “medical necessity” of each service. Showing medical necessity basically means that you justify your treatment choice (CPT code) by linking it to an appropriate diagnosis, symptom or complaint (ICD-9 code). Up to four ICD-9 codes can be linked to each CPT code on a HCFA-1500 form.

For example, a patient in the office for routine diabetes monitoring also complains of chest pain suggesting angina pectoris. As part of the work-up that day, you perform an ECG in your office. On your claim form, however, you list only the ICD-9 code for diabetes. In all likelihood, the insurer won't pay for the ECG because it's not clear from the claim form why the test was medically necessary. The ICD-9 code for chest pain or angina pectoris should also have been listed to indicate the medical necessity for the ECG Link the diagnosis code (ICD-9) to the service code (CPT) on the insurance claim form to identify why the service was rendered, thereby establishing medical necessity.

Here is an another example
if you cut your finger and the doctor repairs the cut, there is a procedure code to put on the claim form. The code is recognized by coders, and insurance company claims software. Let’s look at the cut on the finger. To convert the repair to a CPT code, you need to know the length of the wound, in centimetres so you can select the correct CPT code. For the purpose of this example. You have a 1cm simple cut on your index finger. The repair of this cut would be 12001. Every procedure performed MUST be supported by a correct diagnosis code or ICD-9 code. The diagnosis or ICD-9 code for an unspecified wound of the finger would be 883.0. Now, if you saw ICD-9 code 042 used with CPT code 12001, you would be confused. That would be like saying the doctor sutured the patient’s finger cut because the patient had AIDS. Therefore it doesn’t make sense to suture a wound if there is no open wound diagnosis.

 

        

Read More
Posted in | No comments

ZK upload PDF to server and show in the screen using MVVM

Posted on 03:42 by Unknown

Simple example to upload PDF file in the server and show the content using iframe.

<zk>
<window id="test" border="normal" height="98%"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('org.zk.example.FileUploadVM')">
<label value="You are using: ${desktop.webApp.version}" />
<separator></separator>
<label
value="Example for File upload to the server and display it" />
<separator></separator>
<hbox>
<label value="Upload any PDF File" />
<button label="Upload" upload="true"
onUpload="@command('onUploadPDF',upEvent=event)">
</button>
<button label="Show PDF" visible="@load(vm.fileuploaded)"
onClick="@command('showPDF')">
</button>
</hbox>

<iframe height="100%" width="100%" id="reportframe"
content="@bind(vm.fileContent)">
</iframe>
</window>




</zk>

ViewModel


package org.zk.example;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar;

import org.zkoss.bind.BindContext;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.io.Files;
import org.zkoss.util.media.AMedia;
import org.zkoss.util.media.Media;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Iframe;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Window;

public class FileUploadVM {

private String filePath;
private boolean fileuploaded = false;
AMedia fileContent;

@Wire("#test")
private Window win;

public AMedia getFileContent() {
return fileContent;
}

public void setFileContent(AMedia fileContent) {
this.fileContent = fileContent;
}

public boolean isFileuploaded() {
return fileuploaded;
}

public void setFileuploaded(boolean fileuploaded) {
this.fileuploaded = fileuploaded;
}

@AfterCompose
public void initSetup(@ContextParam(ContextType.VIEW) Component view)
{
Selectors.wireComponents(view, this, false);

}

@Command
@NotifyChange("fileuploaded")
public void onUploadPDF(
@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx)
throws IOException {

UploadEvent upEvent = null;
Object objUploadEvent = ctx.getTriggerEvent();
if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
upEvent = (UploadEvent) objUploadEvent;
}
if (upEvent != null) {
Media media = upEvent.getMedia();
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH); // Note: zero based!
int day = now.get(Calendar.DAY_OF_MONTH);
filePath = Executions.getCurrent().getDesktop().getWebApp()
.getRealPath("/");
String yearPath = "\\" + "PDFs" + "\\" + year + "\\" + month + "\\"
+ day + "\\";
filePath = filePath + yearPath;
File baseDir = new File(filePath);
if (!baseDir.exists()) {
baseDir.mkdirs();
}

Files.copy(new File(filePath + media.getName()),
media.getStreamData());
Messagebox.show("File Sucessfully uploaded in the path [ ."
+ filePath + " ]");
fileuploaded = true;
filePath = filePath + media.getName();
}
}

@Command
@NotifyChange("fileContent")
public void showPDF() throws IOException {
File f = new File(filePath);
Messagebox.show(" dfdfdfdsfdsf" + filePath);
byte[] buffer = new byte[(int) f.length()];
FileInputStream fs = new FileInputStream(f);
fs.read(buffer);
fs.close();
ByteArrayInputStream is = new ByteArrayInputStream(buffer);
fileContent = new AMedia("report", "pdf", "application/pdf", is);



}
}
Read More
Posted in Today Tech Stuff, ZK Framework | No comments
Newer Posts Older Posts Home
Subscribe to: Posts (Atom)

Popular Posts

  • ZK Example for inline Editing with Add New and Delete
    I am quite impressed on this demo from ZK . But adding new record and delete existing record is missing as part of typical CRUD. So i thoug...
  • EDI 5010 Documentation 837 Professional - Loop 2010BB Payer Name
    2010BB Payer Name          In this loop, all the information will be taken from Insurance master screen. Take a look of our sample screen...
  • EDI 5010 Documentation–837 - BHT - Beginning of Hierarchical Transaction
    BHT – Beginning of Hierarchical Transaction Loop Seg ID Segment Name Format Length Ref# Req Value   BHT Beginning of Hier...
  • Hibernate Validator Example 2
    In this example, we will see some more validation constraints such as @email, @past, @length, etc. And also we will also define custom error...
  • ZK Passing Parameter between two files using MVVM–Part 1
    Overview This is the first series of articles about Passing parameter between two zul files using MVVM Design pattern .This article will fo...
  • MVVM Command annotation and Notify change example
    Here is an example, how to pass parameter on a zul through MVVM Command binding annotation. ZK URL http://books.zkoss.org/wiki/ZK%20Develo...
  • History of Present Illness
    HPI - One of the main component of Clinical History. What is an HPI ? The history of present illness (HPI) is a chronological description...
  • Patient Demographics
    Patient browse (search) is the key element for any EMR / PMS Software. In my past 15 years experience, i involved more than 5 times in desig...
  • ViewModel Class Java Annotation @Init, @NotifyChange, @Command
    In following sections we'll list all syntaxes that can be used in implementing a ViewModel and applying ZK bind annotation. The ZK binde...
  • Good Website Design Links
    Form Design Label Placement in Forms International Address Fields in Web Forms 40 Eye-Catching Registration Pages blog-comment-form-...

Categories

  • Billing Process
  • C Workbook
  • C++ Workbook
  • Eclipse Tips
  • EDI 5010
  • EMR Appointment Features
  • EMR Labs Stuff
  • EMR PMS Links
  • EMR Use cases
  • EMR Vital Sign
  • Good Website Design
  • Hibernate Criteria Queries
  • Hibernate Introduction
  • Hibernate Introduction Setup
  • Hibernate Mapping
  • Hibernate POC
  • Hibernate Validator
  • Hibernate–Java Environment setup
  • HPI
  • Java
  • Maven
  • MU Certification
  • NPI
  • PQRS
  • Practice Management System
  • Spring Security
  • Tech Links
  • Today Tech Stuff
  • zk
  • ZK Hibernate
  • ZK 5 Databinding
  • ZK Application
  • ZK Calling Another ZUL
  • ZK CheckBox
  • ZK CreateComponents
  • ZK CSS
  • ZK extended Components
  • ZK Foreach
  • ZK Forum Posts
  • ZK Framework
  • ZK Hibernate Setup
  • ZK ID Space
  • ZK Include
  • ZK Installation
  • ZK iReport
  • ZK Layout
  • ZK Listitem Pagination
  • ZK Message Box
  • ZK MVC
  • ZK MVC Combox Box
  • ZK MVC CRUD Examples
  • ZK MVC Listbox
  • ZK MVVM
  • ZK MVVM Combo
  • ZK MVVM CRUD
  • ZK MVVM ListBox
  • ZK Spring
  • ZK TextBox

Blog Archive

  • ▼  2013 (105)
    • ►  December (3)
    • ►  September (7)
    • ▼  August (13)
      • HL7 Parsing–My Own Parser
      • ZK Dropupload example
      • Hibernate Custom validator to validate Multiple em...
      • ZK List box inline Editing with Add New and Delete...
      • ZK Example for inline Editing with Add New and Delete
      • Patient Demographics and Patient cases
      • How to get Current Date and Time and store in the ...
      • Maintaining Patient Insurance
      • EDI Transactions
      • Health care Coding system
      • ZK upload PDF to server and show in the screen us...
      • ZK Quick InputBox
      • HL7 Parsing
    • ►  July (1)
    • ►  June (11)
    • ►  May (3)
    • ►  April (14)
    • ►  March (19)
    • ►  February (21)
    • ►  January (13)
  • ►  2012 (177)
    • ►  December (1)
    • ►  November (13)
    • ►  October (19)
    • ►  September (24)
    • ►  August (26)
    • ►  July (6)
    • ►  June (37)
    • ►  May (30)
    • ►  April (16)
    • ►  March (1)
    • ►  January (4)
  • ►  2011 (5)
    • ►  December (1)
    • ►  November (1)
    • ►  July (1)
    • ►  June (1)
    • ►  April (1)
  • ►  2010 (1)
    • ►  September (1)
Powered by Blogger.

About Me

Unknown
View my complete profile