Practice Barometers Report

For users or potential users.
Post Reply
mikebarrdds
Posts: 28
Joined: Tue Jun 24, 2014 9:15 pm

Practice Barometers Report

Post by mikebarrdds » Thu Jul 24, 2014 6:29 am

Hello! New user here. I switched over from a very old version of Softdent (9.1) running on a Windows 98 machine. No kidding.

We are loving Open Dental. It's a fantastic program.

I was wondering if anyone here can help guide me on this question. One of my favorite reports in Softdent was called "Practice Barometers." It looks like this:

Image

I could compare any two time periods. So, at the end of each month I run a comparison to the same month and a Y-T-D in the previous year. At the end of the year, I run a Years' End comparison.

Is there a way to set this up?

Thanks!

Mike

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Thu Jul 24, 2014 8:30 am

Like this?
Image

I have it setup for our office and my beta testers to be automatically emailed at the end of every day. I've got quite a bit going on in the backend outside of Open Dental.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Thu Jul 24, 2014 8:32 am

Welcome to this Forum, BTW. I've seen you over at Dental Town.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

mikebarrdds
Posts: 28
Joined: Tue Jun 24, 2014 9:15 pm

Re: Practice Barometers Report

Post by mikebarrdds » Thu Jul 24, 2014 3:55 pm

Hi Kevin,

Thanks for the welcome. Yeah... I "occasionally" post on Dentaltown. :wink:

While your dashboard looks cool, it doesn't provide what I'm looking for. I'd like to duplicate the report in my example above. I want to be able to compare the metrics for two different periods of time.

At the end of this month, for example, I want to compare my metrics for the same month in the previous year. Compare this July's numbers to last July's numbers. And, then I also compare YTD for this year compared to the same period last year.

User avatar
Justin Shafer
Posts: 596
Joined: Sat Jul 28, 2007 7:34 pm
Location: Fort Worth, TX.

Re: Practice Barometers Report

Post by Justin Shafer » Thu Jul 24, 2014 4:08 pm

I like Kevin's idea so far. It is easy.

Sup Mike! Welcome aboard!

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Thu Jul 24, 2014 9:39 pm

mikebarrdds wrote:At the end of this month, for example, I want to compare my metrics for the same month in the previous year. Compare this July's numbers to last July's numbers. And, then I also compare YTD for this year compared to the same period last year.
I'll see what I can whip up. I think I can come up with something for you.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Fri Jul 25, 2014 6:44 am

In your previous software, how was the missed appointment production calculated? Was it based on empty time on the schedule? Or did the software track the production for cancelled/no show appointments?
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

mikebarrdds
Posts: 28
Joined: Tue Jun 24, 2014 9:15 pm

Re: Practice Barometers Report

Post by mikebarrdds » Fri Jul 25, 2014 6:50 am

KevinRossen wrote:In your previous software, how was the missed appointment production calculated? Was it based on empty time on the schedule? Or did the software track the production for cancelled/no show appointments?
I believe (but not sure) that it's based on cancelled / no show appts. I will say that metric wasn't important to me.

The main things I like to compare are (obviously) production and collections. Also new patients, # of patients seen.

It helps me see how I'm doing this year compared to last year. What is the trend?

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Fri Jul 25, 2014 10:28 am

mikebarrdds wrote: I believe (but not sure) that it's based on cancelled / no show appts. I will say that metric wasn't important to me.

The main things I like to compare are (obviously) production and collections. Also new patients, # of patients seen.

It helps me see how I'm doing this year compared to last year. What is the trend?
Ok, I assumed that was the case. I've got a query for you. I really like the report, so I'll use it for our office, too. Make a lot of sense to look at things this way.

I have a couple caveats about it:
1) There's not an easy way to make the report pivot from columns to rows. To make it look the way you had it in SoftDent(?) will require setting up a spreadsheet to format it. I can help with that if you'd like.
2) I'm not sure if there's a way to track historical active/inactive patients. There might be, but I'm not sure how to do. I left it off this report for now.
3) For the hours to work, you'll need to have your schedule in Open Dental setup. When we converted from PracticeWorks (SoftDent's cousin), that was not something that was converted. It was important for me to have that in our reports, so I backdated our schedule. Only took about 1-2 hours.

The only other thing that I know would be an issue is if you have MySQL setup using replication. That's not the standard installation, so it is unlikely you're using it.

You'll need to update the 6 fields at the top corresponding to the period dates and production goals. The goals are based on the gross number, since that's what it looks like the old report was based on. My personal opinion is that net production is the only number that really matters. I can adjust the report to only look at net if you'd like.

Here you go. Let me know if you have any questions/feedback:

Code: Select all

/* Period 1 */
SET	@FromDate1='2013-06-01', 
	@ToDate1='2013-06-30', 
	@ProdGoal1=200000;
/* Period 2 */
SET	@FromDate2='2014-06-01', 
	@ToDate2='2014-06-30', 
	@ProdGoal2=200000;
/* Table for Period 1 */
DROP TABLE IF EXISTS t1;
CREATE TABLE t1( 
Period VARCHAR(35),
PTsSeen double NOT NULL DEFAULT 0,
NPsSeen double NOT NULL DEFAULT 0,
NPPct VARCHAR(6),
GrossProd double NOT NULL DEFAULT 0,
ProdGoal double NOT NULL DEFAULT 0,
ProdGoalPct VARCHAR(6),
EstHours double NOT NULL DEFAULT 0,
GrossPerHour double NOT NULL DEFAULT 0,
GrossPerPt double NOT NULL DEFAULT 0,
NetProd double NOT NULL DEFAULT 0,
NetPerPt double NOT NULL DEFAULT 0,
NetPerHour double NOT NULL DEFAULT 0,
Collection double NOT NULL DEFAULT 0,
CollectRatio VARCHAR(8),
PatCollect double NOT NULL DEFAULT 0,
InsCollect double NOT NULL DEFAULT 0);
/* Select Period 1 Dates */
INSERT INTO t1(Period)
SELECT CONCAT(@FromDate1,' through ',@ToDate1) AS 'Period';
/* Count Patients Seen */
DROP TABLE IF EXISTS t2;
CREATE TABLE t2
SELECT COUNT(DISTINCT PatNum) AS 'PTsSeen'
FROM procedurelog
WHERE ProcDate BETWEEN @FromDate1 AND @ToDate1 AND ProcStatus=2;
UPDATE t1,t2 SET t1.PTsSeen=t2.PTsSeen;
DROP TABLE IF EXISTS t2;
/* Count New Patients Seen */
CREATE TABLE t2
SELECT COUNT(DISTINCT p.PatNum) AS 'NPsSeen'
FROM patient p LEFT JOIN procedurelog pl ON p.PatNum=pl.PatNum
WHERE (pl.ProcDate BETWEEN @FromDate1 AND @ToDate1 AND pl.ProcStatus=2) AND p.DateFirstVisit BETWEEN @FromDate1 AND @ToDate1;
UPDATE t1,t2 SET t1.NPsSeen=t2.NPsSeen;
DROP TABLE IF EXISTS t2;
UPDATE t1 SET NPPct=CONCAT(ROUND((NPsSeen/PTsSeen*100),1),'%');
/*Gross Prod*/
CREATE TABLE t2
SELECT SUM(pl.ProcFee*(pl.UnitQty+pl.BaseUnits)) AS 'GrossProd'
FROM procedurelog pl WHERE pl.ProcStatus=2 AND DATE(pl.ProcDate) BETWEEN @FromDate1 AND @ToDate1;
UPDATE t1,t2 SET t1.GrossProd=t2.GrossProd;
UPDATE t1 SET ProdGoal=@ProdGoal1;
UPDATE t1 SET ProdGoalPct=CONCAT(ROUND((GrossProd/ProdGoal*100),1),'%');
UPDATE t1 SET GrossPerPt=ROUND(GrossProd/PTsSeen,2);
DROP TABLE IF EXISTS t2;
/*Scheduled Hours*/
CREATE TABLE t2
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(s.StopTime, s.StartTime)))/(60*60),1) AS 'EstHours'
FROM schedule s
WHERE s.SchedDate BETWEEN @FromDate1 AND @ToDate1 AND SchedType = 1 AND s.SchedDate < CURDATE();
UPDATE t1,t2 SET t1.EstHours=t2.EstHours;
UPDATE t1 SET GrossPerHour=ROUND(GrossProd/EstHours,2);
DROP TABLE IF EXISTS t2;
/*Net Production*/
CREATE TABLE t2( 
Adjustments double NOT NULL DEFAULT 0,
WriteOff double NOT NULL DEFAULT 0);
INSERT INTO t2(Adjustments)
SELECT SUM(AdjAmt) AS 'Adjustments' 
FROM adjustment WHERE AdjDate BETWEEN @FromDate1 AND @ToDate1;
DROP TABLE IF EXISTS t3;
CREATE TABLE t3
SELECT SUM(WriteOff) AS 'WriteOff'
FROM claimproc WHERE (Status=1 OR Status=4 OR Status=0) AND ProcDate BETWEEN @FromDate1 AND @ToDate1;
UPDATE t2,t3 SET t2.WriteOff=t3.WriteOff;
DROP TABLE IF EXISTS t3;
UPDATE t1,t2 SET t1.NetProd=ROUND(t1.GrossProd+t2.Adjustments-IFNULL(t2.WriteOff,0),2);
UPDATE t1 SET NetPerHour=ROUND(NetProd/EstHours,2);
UPDATE t1 SET NetPerPt=ROUND(NetProd/PTsSeen,2);
DROP TABLE IF EXISTS t2;
/*Collection*/
CREATE TABLE t2( 
Month int NOT NULL,
PatCollect double NOT NULL DEFAULT 0,
InsCollect double NOT NULL DEFAULT 0);
INSERT INTO t2(PatCollect)
SELECT ROUND(SUM(SplitAmt),2) AS 'PatCollect' 
FROM paysplit WHERE DatePay BETWEEN @FromDate1 AND @ToDate1;
DROP TABLE IF EXISTS t3;
CREATE TABLE t3
SELECT ROUND(SUM(cp.InsPayAmt),2) AS 'InsCollect'
FROM claimproc cp INNER JOIN claimpayment cpay ON cpay.ClaimPaymentNum=cp.ClaimPaymentNum
WHERE cpay.CheckDate BETWEEN @FromDate1 AND @ToDate1 AND cp.Status IN(1,4);
UPDATE t2,t3 SET t2.InsCollect=t3.InsCollect;
DROP TABLE IF EXISTS t3;
UPDATE t1,t2 SET t1.Collection=(t2.InsCollect+t2.PatCollect);
UPDATE t1,t2 SET t1.PatCollect=t2.PatCollect;
UPDATE t1,t2 SET t1.InsCollect=t2.InsCollect;
DROP TABLE IF EXISTS t2;
UPDATE t1 SET CollectRatio=CONCAT(ROUND((Collection/NetProd*100),1),'%');
/* Table for Period 2 */
DROP TABLE IF EXISTS t2;
CREATE TABLE t2( 
Period VARCHAR(35),
PTsSeen double NOT NULL DEFAULT 0,
NPsSeen double NOT NULL DEFAULT 0,
NPPct VARCHAR(6),
GrossProd double NOT NULL DEFAULT 0,
ProdGoal double NOT NULL DEFAULT 0,
ProdGoalPct VARCHAR(6),
EstHours double NOT NULL DEFAULT 0,
GrossPerHour double NOT NULL DEFAULT 0,
GrossPerPt double NOT NULL DEFAULT 0,
NetProd double NOT NULL DEFAULT 0,
NetPerPt double NOT NULL DEFAULT 0,
NetPerHour double NOT NULL DEFAULT 0,
Collection double NOT NULL DEFAULT 0,
CollectRatio VARCHAR(8),
PatCollect double NOT NULL DEFAULT 0,
InsCollect double NOT NULL DEFAULT 0);
/* Select Period 1 Dates */
INSERT INTO t2(Period)
SELECT CONCAT(@FromDate2,' through ',@ToDate2) AS 'Period';
/* Count Patients Seen */
DROP TABLE IF EXISTS t3;
CREATE TABLE t3
SELECT COUNT(DISTINCT PatNum) AS 'PTsSeen'
FROM procedurelog
WHERE ProcDate BETWEEN @FromDate2 AND @ToDate2 AND ProcStatus=2;
UPDATE t2,t3 SET t2.PTsSeen=t3.PTsSeen;
DROP TABLE IF EXISTS t3;
/* Count New Patients Seen */
CREATE TABLE t3
SELECT COUNT(DISTINCT p.PatNum) AS 'NPsSeen'
FROM patient p LEFT JOIN procedurelog pl ON p.PatNum=pl.PatNum
WHERE (pl.ProcDate BETWEEN @FromDate2 AND @ToDate2 AND pl.ProcStatus=2) AND p.DateFirstVisit BETWEEN @FromDate2 AND @ToDate2;
UPDATE t2,t3 SET t2.NPsSeen=t3.NPsSeen;
DROP TABLE IF EXISTS t3;
UPDATE t2 SET NPPct=CONCAT(ROUND((NPsSeen/PTsSeen*100),1),'%');
/*Gross Prod*/
CREATE TABLE t3
SELECT SUM(pl.ProcFee*(pl.UnitQty+pl.BaseUnits)) AS 'GrossProd'
FROM procedurelog pl WHERE pl.ProcStatus=2 AND DATE(pl.ProcDate) BETWEEN @FromDate2 AND @ToDate2;
UPDATE t2,t3 SET t2.GrossProd=t3.GrossProd;
UPDATE t2 SET ProdGoal=@ProdGoal1;
UPDATE t2 SET ProdGoalPct=CONCAT(ROUND((GrossProd/ProdGoal*100),1),'%');
UPDATE t2 SET GrossPerPt=ROUND(GrossProd/PTsSeen,2);
DROP TABLE IF EXISTS t3;
/*Scheduled Hours*/
CREATE TABLE t3
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(s.StopTime, s.StartTime)))/(60*60),1) AS 'EstHours'
FROM schedule s
WHERE s.SchedDate BETWEEN @FromDate2 AND @ToDate2 AND SchedType = 1 AND s.SchedDate < CURDATE();
UPDATE t2,t3 SET t2.EstHours=t3.EstHours;
UPDATE t2 SET GrossPerHour=ROUND(GrossProd/EstHours,2);
DROP TABLE IF EXISTS t3;
/*Net Production*/
CREATE TABLE t3( 
Adjustments double NOT NULL DEFAULT 0,
WriteOff double NOT NULL DEFAULT 0);
INSERT INTO t3(Adjustments)
SELECT SUM(AdjAmt) AS 'Adjustments' 
FROM adjustment WHERE AdjDate BETWEEN @FromDate2 AND @ToDate2;
DROP TABLE IF EXISTS t4;
CREATE TABLE t4
SELECT SUM(WriteOff) AS 'WriteOff'
FROM claimproc WHERE (Status=1 OR Status=4 OR Status=0) AND ProcDate BETWEEN @FromDate2 AND @ToDate2;
UPDATE t3,t4 SET t3.WriteOff=t4.WriteOff;
DROP TABLE IF EXISTS t4;
UPDATE t2,t3 SET t2.NetProd=ROUND(t2.GrossProd+t3.Adjustments-IFNULL(t3.WriteOff,0),2);
UPDATE t2 SET NetPerHour=ROUND(NetProd/EstHours,2);
UPDATE t2 SET NetPerPt=ROUND(NetProd/PTsSeen,2);
DROP TABLE IF EXISTS t3;
/*Collection*/
CREATE TABLE t3( 
Month int NOT NULL,
PatCollect double NOT NULL DEFAULT 0,
InsCollect double NOT NULL DEFAULT 0);
INSERT INTO t3(PatCollect)
SELECT ROUND(SUM(SplitAmt),2) AS 'PatCollect' 
FROM paysplit WHERE DatePay BETWEEN @FromDate2 AND @ToDate2;
DROP TABLE IF EXISTS t4;
CREATE TABLE t4
SELECT ROUND(SUM(cp.InsPayAmt),2) AS 'InsCollect'
FROM claimproc cp INNER JOIN claimpayment cpay ON cpay.ClaimPaymentNum=cp.ClaimPaymentNum
WHERE cpay.CheckDate BETWEEN @FromDate2 AND @ToDate2 AND cp.Status IN(1,4);
UPDATE t3,t4 SET t3.InsCollect=t4.InsCollect;
DROP TABLE IF EXISTS t4;
UPDATE t2,t3 SET t2.Collection=(t3.InsCollect+t3.PatCollect);
UPDATE t2,t3 SET t2.PatCollect=t3.PatCollect;
UPDATE t2,t3 SET t2.InsCollect=t3.InsCollect;
DROP TABLE IF EXISTS t3;
UPDATE t2 SET CollectRatio=CONCAT(ROUND((Collection/NetProd*100),1),'%');
/* Build Report */
SELECT * FROM t1
UNION
SELECT * FROM t2
UNION 
SELECT 	'Change',
		CONCAT(ROUND(((t2.PTsSeen-t1.PTsSeen)/t1.PTsSeen*100),1),'%'),
		CONCAT(ROUND(((t2.NPsSeen-t1.NPsSeen)/t1.NPsSeen*100),1),'%'),
		'',
		CONCAT(ROUND(((t2.GrossProd-t1.GrossProd)/t1.GrossProd*100),1),'%'),
		'',
		'',
		'',
		CONCAT(ROUND(((t2.GrossPerHour-t1.GrossPerHour)/t1.GrossPerHour*100),1),'%'),
		CONCAT(ROUND(((t2.GrossPerPt-t1.GrossPerPt)/t1.GrossPerPt*100),1),'%'),
		CONCAT(ROUND(((t2.NetProd-t1.NetProd)/t1.NetProd*100),1),'%'),
		CONCAT(ROUND(((t2.NetPerPt-t1.NetPerPt)/t1.NetPerPt*100),1),'%'),
		CONCAT(ROUND(((t2.NetPerHour-t1.NetPerHour)/t1.NetPerHour*100),1),'%'),
		CONCAT(ROUND(((t2.Collection-t1.Collection)/t1.Collection*100),1),'%'),
		'',
		CONCAT(ROUND(((t2.PatCollect-t1.PatCollect)/t1.PatCollect*100),1),'%'),
		CONCAT(ROUND(((t2.InsCollect-t1.InsCollect)/t1.InsCollect*100),1),'%')
FROM t1,t2;
DROP TABLE IF EXISTS t1,t2;
EDIT: Had a formula reversed.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

spolevoy
Posts: 74
Joined: Wed Oct 17, 2012 4:45 am

Re: Practice Barometers Report

Post by spolevoy » Fri Jul 25, 2014 12:08 pm

Hey Mike,

Not to divert the conversation, but have you looked at addding mopsy's YAPI?

It's an intra-office messaging, appointment reminder, recall management, patient communication system that also does metrics :D

hmm...how do I attach an image? do I need to upload it to some pic sharing site first? that's annoying

anything for you Mike
Image

steve

Jay
Posts: 272
Joined: Fri Aug 06, 2010 10:01 am

Re: Practice Barometers Report

Post by Jay » Fri Jul 25, 2014 2:56 pm

How do you generate this kind of report?
KevinRossen wrote:Like this?
Image

I have it setup for our office and my beta testers to be automatically emailed at the end of every day. I've got quite a bit going on in the backend outside of Open Dental.

mikebarrdds
Posts: 28
Joined: Tue Jun 24, 2014 9:15 pm

Re: Practice Barometers Report

Post by mikebarrdds » Fri Jul 25, 2014 5:20 pm

Hi Kevin,

Thanks for your efforts!

Pardon my newbie questions. I'm not familiar with all the coding in the query? Softdent could generate user-customized reports without having to be a coding wizard. All I had to do is check off what I wanted to appear in the report.

How do I change the date ranges? Is that done in the query code?

Thanks!

Mike

mikebarrdds
Posts: 28
Joined: Tue Jun 24, 2014 9:15 pm

Re: Practice Barometers Report

Post by mikebarrdds » Fri Jul 25, 2014 5:23 pm

spolevoy wrote:Hey Mike,

Not to divert the conversation, but have you looked at addding mopsy's YAPI?

It's an intra-office messaging, appointment reminder, recall management, patient communication system that also does metrics :D
Thanks, Steve. I've heard of YAPI. But, I'm really not interested in adding more software (that costs more than my PMS). I don't need or use intra-office messaging (OD does that anyway). My practice simply isn't that big. As for patient communications, I might be interested in that in the foreseeable future. But, from what I've seen, YAPI doesn't do that nearly as well as systems like Lighthouse, for example.

Mike

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Sat Jul 26, 2014 7:21 am

mikebarrdds wrote:How do I change the date ranges? Is that done in the query code?
At the very top change each of these:
@FromDate1=
@ToDate1=
@ProdGoal1=
@FromDate2=
@ToDate2=
@ProdGoal2=

Just change the numbers inside the single quotation marks.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

KevinRossen
Posts: 293
Joined: Mon Apr 22, 2013 8:49 am
Location: Dallas, TX
Contact:

Re: Practice Barometers Report

Post by KevinRossen » Sat Jul 26, 2014 7:44 am

Jay wrote:How do you generate this kind of report?
KevinRossen wrote:Like this?
Image

I have it setup for our office and my beta testers to be automatically emailed at the end of every day. I've got quite a bit going on in the backend outside of Open Dental.
It's a combination of running MySQL queries from batch scripts and HIGHLY customized excel spreadsheets/charts. I don't have to manually interact with it. My setup emails it to me at 6:45 every day. Check the link in my signature for a few more details.
Kevin Rossen
Office Manager, Rossen Dental
Founder, DivergentDental.com
Image

d2dental
Posts: 31
Joined: Wed Sep 01, 2010 10:00 pm
Location: Mumbai, India
Contact:

Re: Practice Barometers Report

Post by d2dental » Thu Aug 21, 2014 7:24 am

Can we extend this report for multiple time period/ years.

Post Reply