New/Established Patients

One of the biggest problems our Billing department deals with is incorrect service charges. I don’t claim to understand all the ins and outs, but I get the basic idea: There are charges for new patients, and charges for established patients. Put the wrong charge on a visit, it gets kicked back by the insurance, Billing has to deal with it. We needed a way for the staff to more easily identify a patient as new or established.

Mistakes are unavoidable, and we do what we can to reduce the risk. Ultimately we can’t do the user’s job for them, so assuming we don’t want to implement some kind of auto-correction trigger (and we do not) the best we can do is try to present some visual indicator that the patient is either new or established.

We’re going to put that information in the patient banner. It will take a few steps, and will involve a combination of SQL, MEL, and some text file manipulation.

The first thing we’re going to do is create a scalar function that tells us whether a patient is new or established. We could have this function return a bit value, but as we intend to display text in our banner, we might as well cut to the chase and have the function return that text.

The function is going to return either “Established Patient” or “New Patient.” We look for a completed appointment for this patient in the past three years (Appointments.ApptKind = 1, .ApptStatusMId = 311, and the DATEDIFF() gets us close enough to three years), specifically at one of our primary care facilities (that’s the INNER JOIN to cus_fnFacilities()).

We also need to see a service charge on that visit. If the patient was seen but they forgot the service charge, we’re still counting this as a new patient for billing purposes. So we link the appointment through DOCUMENT to ORDERS, looking for a completed service charge in that array of CODE values,

If we find a service charge from a primary care facility in the last three years, they’re established. If not, they’re new.

So now what do we do with it? It would be nice if we could call that function directly from the patient banner. Maybe there’s a way to do that, but I haven’t found it. As far as I can see, the banner can only pull data from tables and views. So let’s put it in the PatientProfile table.

Wait, you’re going to add a computed column to a GE table? Can you do that? Sure, why not? We’re not adding it to any indexes (apart from the PK, I suppose), and Centricity is never going to call for it, so it shouldn’t get in anyone’s way. If we were deleting a column, yeah that would be bad. But adding one should be harmless. (And confirming that is why we have a dev environment.)

(As an aside, I have considered moving this column to the PERSON view, or creating a new view entirely. I’m generally not a “view guy,” and I’ll be posting on that topic in the near future. I’d love to hear some feedback on this point.)

Why didn’t we make this computed column PERSISTED? Wouldn’t that make it more efficient, assuming the additional storage requirement isn’t an issue? That’s an excellent point, except for one little complication. Go look at the function and tell me in the comments why I didn’t make this column PERSISTED. Or highlight this invisi-text if you want to cheat: CURRENT_TIMESTAMP makes this a non-deterministic function, and you can’t persist a computed column based on one of those.

Now we have our computed column, it’s time to put it into our patient banner. The first thing we need to do is create a data object that the banner can access. We do this by modifying one of the mldefs*.txt files in the application directory. I chose mldefs3.txt, and added this block to it:

Object: _EstablishedPatient
    Refresh:  RBook
    Property: Snapshot
    Property: Prepare
    Field:    NewEstPatient Type: String Length: 25
    Filter:   PatientFilter, PatientProfileId = Patient.PatientProfileId Hidden

I’m not going to lie to you, I have no idea what half of that means. But you can learn a lot by reverse engineering. Look at your existing patient banner code, and see what data objects are being called. Go look at how those are being defined. Where you can understand what they did, you can modify those parts to meet your needs. Where you can’t figure it out, just copy what’s there and test it out. This is what the dev environment is for, right?

In this case, there was already a very similar object that pulled data from PatientProfile.  I don’t have a clue what Refresh or Property are, so I just copied them. Field appears to be a definition of the table column being pulled, easy enough. Filter is a bit less clear, but it looks a lot like a WHERE clause, doesn’t it? I copied what was there, and it worked.

Next I discovered that this object needs to be exposed to Centricity through some sort of global variable, which gets set in mellib.txt. Okay, so let’s do that.

global _MELNewEstPatient = _EstablishedPatient

Now we can log into Centricity and update our patient banner. Whether you’re doing this in dev or not, I recommend making a copy of your banner and testing there first. The code is really straightforward:

local a = getRow("_MELNewEstPatient",i,"NewEstPatient")
return a

That’s it! Insert that text wherever you want the new/established text to appear and you should be all set. Now when a user opens a chart, the status is right there in front of them.


Leave a Reply