OpenEMR Billing Setup Howtos

From OpenEMR Project Wiki
  • NOTE: The following is for Version 3.1.x and 3.2.x

Preparing for Billing and using the Fee Sheet

  • It's important that Administration->Globals->Features->CMS 1500 Paper Form Format is set to 02/12 for ICD 10 compatibility. (please note this option was removed in version 5.0.1)

Load and Update Billing Codes

Linux Instructions

  1. Modify the openemr/contrib/util/load_icd_desc.plx file:
    • Place database name at line 36 (get this from the openemr/library/sqlconf.php file)
    • Comment out line 45 and 46
    • Uncomment line 48 and 49, and substitute the your sql username and database for username and password in this line (line 48). (get these from theopenemr/library/sqlconf.php file )
  2. Execute the script:
perl /var/www/openemr/contrib/util/load_icd_desc.plx

Windows Instructions

  1. Modify the c:\xampp\htdocs\openemr\contrib\load_icd_desc.plx file:
    • Place database name at line 36 (get this from the openemr/library/sqlconf.php file)
    • Comment out line 45 and 46
    • Uncomment line 48 and 49, and substitute the your sql username and database for username and password in this line (line 48). (get these from theopenemr/library/sqlconf.php file )
  2. Install ActivePerl (if not already installed, (it defaults to C:\Perl directory, which is fine)):
  3. Configure ActivePerl and run the script (via two below commands):
C:\Perl\bin\ppm install DBD-MySQL
C:\Perl\bin\perl c:\xampp\htdocs\openemr\contrib\load_icd_desc.plx

Detailed Windows Instructions

Before starting this, you should make a duplicate copy of your entire Xampp directory, so you can verify all works correctly before you actually change real data, unless you already have the ability to recover if your files are damaged. I prefer to rename the "Real" data as "Xampp310Real", and then name the copy "Xampp" so it will run properly. To copy, Logout from OpenEMR and stop both your Apache and MySQL services. If you used the pre 3.1.0 and upgraded, you probably are using the Xampp "doggy bone" found in your taskbar at lower right, where you should stop each of MySQL and Apache in that order, then select the "Exit" button - remember to re-start all those before trying to start OpenEMR again. If you used the one-click to install 3.1.0 in windows, it uses the Apache and MySQL services, which can be stopped using the Control Panel - Admin - Services, but that should not be necessary. Those must be restarted, though, to run OpenEMR if you stopped them. You can download Perl from
The following presumes a Windows install of ver 3.1.0 or 3.2.0 of OpenEMR. You may have to make changes if yours is not the same. To use the PLX files in OpenEMR, you must first install a working version of Perl. Save your download to your desired location, but it is advised that you actually do the install to the default location (c:\perl), which is accomplished by running the MSI file after download, which will usually be named like ..\activeperl-ver#-mswin32-x86-s/n.msi If yours does not have the MSI extension, it will not work properly. To install, you simply double-click on the MSI filename and allow it to run. You might need administrator rights. During the install, you should accept all the defaults, which will put all the needed files in the c:\perl location, including all the needed libraries. Once installed, use the Command Prompt to run the following (the Perl install and this are only needed once):
 c:\perl\bin\ppm install DBD-MySQL
The rest of the instructions here assume you have your windows OpenEMR install (including IIS as applicable) in c:\xampp\htdocs\ so you may have to make adjustments if not. You must first edit each of the PLX files you intend to use with data found in the file openemr/library/sqlconf.php at the very top. Why they do not use the same naming convention is again unknown, but the values /.. you must substitute for those shown in the PLX files are found in the first twelve lines of the sqlconf.php file. For example, the utility PLX file to load the ICD9 codes from into the Admin - Services (Superbill in radio view) is openemr/contrib/util/load_icd_desc.plx which must be edited to use. You must first assure you have the latest version so it is /.. compatible with the website where it will be getting the info, and the first change you must make is to assure the correct year is selected - as of October 1, 2009 that should be 2010, which you should change near line 30 for the value "my $START_URL". Below that you should see "my $DBNAME" whose value you will change to the value shown in sqlconf.php at line 10 for $dbase, which is likely "openemr" (make certain to include the quote marks). You will want to comment out lines 45-46 which starts with "my $dbh", and my preference is to copy lines 48-49 to lines 51-52 so I retain the explanation as a commented line, then uncomment lines 51-52 which also start with "my $dbh". Within them you will replace "username" with the value from sqlconf.php line 8 $login which may also be "openemr" (remember to include the quote marks) and replace "password" with the value from sqlconf.php line 9 $pass which can be anything (again remember the quote marks) and save the edited PLX file. Then create a batch file so you have it thereafter to read (note the space between the second perl and the c) for each PLX file you want to use like:
 c:\perl\bin\perl c:\ xampp\htdocs \openemr\contrib\util\load_icd_desc.plx
If you have done all per above, you should be able to run that batch file at any time, once you have the correct year in the plx file, but remember that every update or patch containing the plx file will overwrite yours, so you should make a copy of yours to use as a model (eg. load_icd_desc-copy.plx) in the same util folder, and verify before you run that the settings are correct. Changes must be made any time the website changes (or others), so please be aware the PLX files may NOT be current at all times.
You should make similar changes to any of the other PLX files you wish to use (find their purpose within them), and make a similar batch file for each of those you intend to use. You need not re-install ActivePerl anytime thereafter unless you uninstall it.

Setting Payer Coverage Periods for Billing - Even After Encounters

Changing Payers After Encounters

Using The Calendar For Billing, Meds & Other Tasks

Those who must request Medication Prior Auths, produce scripts in advance of patient appointments, wish to remind patients, etc. without cluttering their own calendar can use the Calendar as a powerful tool by creating a "pseudo User" with calendar privileges. That pseudo user can then be viewed by actual users by using the ctrl-click when viewing their own calendar, which will make the pseudo another "user" alongside their own calendar.
The most powerful way to use it is to create special Calendar Categories for specific needs - patient prompts, OTR, Prior Auth, Needs Script, needs Renewal, etc., with different colors to allow for fast visual selection for processing. Setting these up is done using Admin - Calendar - Categories. These will show up as added types in the Visit Type in Encounter dropdown, as well as within the calendar New Appointment window.
Make certain to select the Pseudo User as the "Provider" when setting these, as the default will be the actual user logged in. Also, to assure greatest likelihood of seeing them (ie not overlooking them) it is best to use the smallest time segments, and use them in the earliest sequence per day available, since the Calendar always opens at the first hour defined in Globals.php. Your Globals.php settings may be set to more than 15 minutes (the default), but that should be a sufficient time element for each of these task reminders.
It is best to NOT allow the automatic creation of an encounter with "@", which can interfere with the normal billing and accounting, but they will show up as upcoming "appointments" in the patient demographics if you link the patient in setting the appointment, which can be a good reminder to the providers, and you can use the other Status characters as appropriate.
These are also a great way to use the "repeat" functions available in the calendar. As with all calendar items, though, you should generally avoid indefinite repeats (ie make an end date for the repeats be no more than three years hence, then update as that approaches).
In use, the provider will ctrl-click to add the pseudo to their calendar listing, which will be a task prompter, and they can checkoff each item using the same "Status" characters. As an example; Joe Holzer needs his Controlled Substance paper script on specific state script form every month. So the provider uses the pseudo user (Tasks) calendar to create a repeating reminder every month a few days before the patient would expect to pick it up, or have it mailed to him. The provider can then prepare them within the state's typically 30 day limit of use, but at the provider's convenience, and have them available for pickup at the front desk, thereby training patients to follow the schedule so as to minimize those Sunday "crises" for meds.
It should be equally obvious the savings of time for prior auths, etc such usage provides. A very useful tool.
By the time you read this there may be a patch for versions 3.1 and above to allow comments for all appointments to display in the Fancy or Outlook Day views, which will allow you to also use the Calendar to remind on issues such as Copays, especially at the new year when annual deductibles often apply, to minimize delay in receipt of your payments due, or for other important messages, which can be added using the "Comments" in the Appointment setting window. Access these in existing appointments by clicking on the Time displayed within them. The comment text displayed is limited only by the size of the displayed block, and will follow the patient name.
Lastly, the Calendar can allow grouping process activities by use of the color codes, to gain the time efficiencies for task consolidation - for example do all prior auth request forms first thing, rather than have such interfere throughout the day disrupting other processes. Best of luck. Let us know via the Users forum if this helps you. Thanks.

Fixing Payer Problems with CMS 1500 or X12: Adjusting OpenEMR Outputs to meet Payer Needs

Please excuse the lack of indents below - the Wiki publications format differently (undesired) if items indent. Follow the indents in the real files.
Some payers and Clearinghouses have problems with OpenEMR outputs, while others work fine with the standard X12 and CMS 1500 outputs.
To correct these, you will make what I refer to a "contingencies", which will occur only in the specific case which you wish to overcome. A fairly frequent problem has been the X12 output for HL when the patient is not the subscriber (for example, the patient is a child of the parent who actually carries the insurance). Some insurers, but NOT ALL, balk at the code which follows "SBR" in the case where HL value is "0" most of the time, but that causes an error if the subscriber is the parent, for example, so we substitute the acceptable "1", and replace the follow-on code with a blank.. To make it work for my particular cases (Aetna and UBH/UHC) I used the common string in their Payer ID to replace the code with a blank using the change below from about line 206. If you are not a programmer, you are strongly advised to seek the services of one of the commercial providers listed on the site as they will be familiar with the issues and the fixes. Because there are so many variables involved, it is not possible to pre-construct for these few problems we are aware of. The code below is found in the file ../library/ which controls the build of the X12 file for submittal:

$PatientHL = 0; // Value was 0 causes HL Loop Children Error at UHC 2/10/09 JCH $Joe = (substr($claim->insuredRelationship(), 0, 2)); // Need to eliminate code after SBR when Pt is not the Insured 2/10/09 JCH if ($Joe != "18") { $PatientHL = "1"; if (substr($claim->x12gsreceiverid(), 0, 6) == "908011") { $Joe = ""; } } ++$edicount; $out .= "HL" . // Loop 2000B Subscriber HL Loop "*$HLcount" . "*$HLBillingPayToProvider" . "*22" . "*$PatientHL" . "~\n";

$HLSubscriber = $HLcount++;

if (!$claim->payerSequence()) { $log .= "*** Error: Insurance information is missing!\n"; } ++$edicount; $out .= "SBR" . // Subscriber Information "*" . $claim->payerSequence() . "*" . $claim->insuredRelationship() . "*" . $claim->groupNumber() . "*" . $claim->groupName() . "*" . $claim->insuredTypeCode() . // applies for secondary medicare "*" . "*" . "*" . "*" . $claim->claimType() . // Zirmed replaces this "~\n";

Similarly, a known issue for a few of the Medicare handlers like NGS has been their insistence on the date being in a "Signature On File" field, despite their published rules to the contrary. Rather than argue, which gets you nowhere, you can simply modify ../library/gen_hcfa_1500.ins.php in the area of the field itself. Note, though, that this file acts via another file for ezpdf, so simple changes in print positions are not always as simple as they seem. In the example below, where they want the date shown in Box 31 of the CMS 1500 form, you must actually allocate space for it in front of the line for 32a (the billing facility NPI) and fill it with blank spaces when the normal print (other than the NGS) is desired, using the code below. I also suggest replacing the FECA value of "39" with "45" near line 92 so those will print as "Other" in the checkbox, since they share the same designation. We have never had a claim rejected for having done that. The date code starts near line 538:

// 31. Signature of Physician or Supplier // FreeB printed the rendering provider's name and the current date here, // but according to my instructions it must be a real signature and date, // or else "Signature on File" or "SOF". put_hcfa(60, 1, 20, 'Signature on File'); // // $tmp = $claim->providerFirstName(); // if ($claim->providerMiddleName()) $tmp .= ' ' . substr($claim->providerMiddleName(),0,1); // put_hcfa(60, 1, 20, $tmp . ' ' . $claim->providerLastName());

// 32. Service Facility Location Information: City State Zip $tmp = $claim->facilityCity() ? ($claim->facilityCity() . ' ') : ; put_hcfa(60, 23, 25, $tmp . $claim->facilityState() . ' ' . $claim->facilityZip());

// 32. Billing Provider: City State Zip $tmp = $claim->billingFacilityCity() ? ($claim->billingFacilityCity() . ' ') : ; put_hcfa(60, 50, 25, $tmp . $claim->billingFacilityState() . ' ' . $claim->billingFacilityZip());

// 31. Form Date: Added Date Printed 7/5/09 for Medicare returns PIA JCH $formdate = " "; if ($ct === 'MB') { $formdate = date('Y-m-d'); }

// 32a. Service Facility NPI put_hcfa(61, 12, 22, $formdate . ' ' . $claim->facilityNPI()); // inserted $formdate & space 7/5/09 JCH

I hope these give you a good idea how to fix these issues. But I again advise that if you are not a strong programmer, you probably would be best to hire one of those who are listed as commercial resources like myself to fix your issue. Even missing a single close-bracket can cause nightmarish behaviors you certainly want to avoid. Good Luck. Let us know if this has helped you. Thanks. Joe Holzer - Idea Man


Note: These directions cover working against the version of OpenEMR maintained in CVS, which is subject to change behaviors at any moment.