Dunning messages on statements, take 2.
[openemr.git] / sites / default / statement.inc.php
blobfcd50f522d9a7479feaeabe9ba6bc73424701bf9
1 <?php
3 // Copyright (C) 2005-2006 Rod Roark <rod@sunsetsystems.com>
4 //
5 // Windows compatibility mods 2009 Bill Cernansky [mi-squared.com]
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // Updated by Medical Information Integration, LLC to support download
13 // and multi OS use - tony@mi-squared..com 12-2009
15 //////////////////////////////////////////////////////////////////////
16 // This is a template for printing patient statements and collection
17 // letters. You must customize it to suit your practice. If your
18 // needs are simple then you do not need programming experience to do
19 // this - just read the comments and make appropriate substitutions.
20 // All you really need to do is replace the [strings in brackets].
21 //////////////////////////////////////////////////////////////////////
23 // The location/name of a temporary file to hold printable statements.
26 $STMT_TEMP_FILE = $GLOBALS['temporary_files_dir'] . "/openemr_statements.txt";
27 $STMT_TEMP_FILE_PDF = $GLOBALS['temporary_files_dir'] . "/openemr_statements.pdf";
29 $STMT_PRINT_CMD = $GLOBALS['print_command'];
32 // This function builds a printable statement or collection letter from
33 // an associative array having the following keys:
35 // today = statement date yyyy-mm-dd
36 // pid = patient ID
37 // patient = patient name
38 // amount = total amount due
39 // to = array of addressee name/address lines
40 // lines = array of lines, each with the following keys:
41 // dos = date of service yyyy-mm-dd
42 // desc = description
43 // amount = charge less adjustments
44 // paid = amount paid
45 // notice = 1 for first notice, 2 for second, etc.
46 // detail = associative array of details
48 // Each detail array is keyed on a string beginning with a date in
49 // yyyy-mm-dd format, or blanks in the case of the original charge
50 // items. Its values are associative arrays like this:
52 // pmt - payment amount as a positive number, only for payments
53 // src - check number or other source, only for payments
54 // chg - invoice line item amount amount, only for charges or
55 // adjustments (adjustments may be zero)
56 // rsn - adjustment reason, only for adjustments
58 // The returned value is a string that can be sent to a printer.
59 // This example is plain text, but if you are a hotshot programmer
60 // then you could make a PDF or PostScript or whatever peels your
61 // banana. These strings are sent in succession, so append a form
62 // feed if that is appropriate.
65 // A sample of the text based format follows:
67 //[Your Clinic Name] Patient Name 2009-12-29
68 //[Your Clinic Address] Chart Number: 1848
69 //[City, State Zip] Insurance information on file
72 //ADDRESSEE REMIT TO
73 //Patient Name [Your Clinic Name]
74 //patient address [Your Clinic Address]
75 //city, state zipcode [City, State Zip]
76 // If paying by VISA/MC/AMEX/Dis
78 //Card_____________________ Exp______ Signature___________________
79 // Return above part with your payment
80 //-----------------------------------------------------------------
82 //_______________________ STATEMENT SUMMARY _______________________
84 //Visit Date Description Amount
86 //2009-08-20 Procedure 99345 198.90
87 // Paid 2009-12-15: -51.50
88 //... more details ...
89 //...
90 //...
91 // skipping blanks in example
94 //Name: Patient Name Date: 2009-12-29 Due: 147.40
95 //_________________________________________________________________
97 //Please call if any of the above information is incorrect
98 //We appreciate prompt payment of balances due
100 //[Your billing contact name]
101 // Billing Department
102 // [Your billing dept phone]
104 function create_statement($stmt) {
105 if (! $stmt['pid']) return ""; // get out if no data
107 // These are your clinics return address, contact etc. Edit them.
108 // TBD: read this from the facility table
110 // Facility (service location)
111 $atres = sqlStatement("select f.name,f.street,f.city,f.state,f.postal_code from facility f " .
112 " left join users u on f.id=u.facility_id " .
113 " left join billing b on b.provider_id=u.id and b.pid = '".$stmt['pid']."' " .
114 " where service_location=1");
115 $row = sqlFetchArray($atres);
117 // Facility (service location)
119 $clinic_name = "{$row['name']}";
120 $clinic_addr = "{$row['street']}";
121 $clinic_csz = "{$row['city']}, {$row['state']}, {$row['postal_code']}";
124 // Billing location
125 $remit_name = $clinic_name;
126 $remit_addr = $clinic_addr;
127 $remit_csz = $clinic_csz;
129 // Contacts
130 $atres = sqlStatement("select f.attn,f.phone from facility f " .
131 " left join users u on f.id=u.facility_id " .
132 " left join billing b on b.provider_id=u.id and b.pid = '".$stmt['pid']."' " .
133 " where billing_location=1");
134 $row = sqlFetchArray($atres);
135 $billing_contact = "{$row['attn']}";
136 $billing_phone = "{$row['phone']}";
138 // dunning message setup
140 // insurance has paid something
141 // $stmt['age'] how old is the invoice
142 // $stmt['dun_count'] number of statements run
143 // $stmt['level_closed'] <= 3 insurance 4 = patient
145 if ($GLOBALS['use_dunning_message']) {
147 if ($stmt['ins_paid'] != 0 || $stmt['level_closed'] == 4) {
149 // do collection messages
150 switch ($stmt{'age'}) {
151 case $stmt{'age'} <= $GLOBALS['first_dun_msg_set']:
152 $dun_message = $GLOBALS['first_dun_msg_text'];
153 break;
154 case $stmt{'age'} <= $GLOBALS['second_dun_msg_set']:
155 $dun_message = $GLOBALS['second_dun_msg_text'];
156 break;
157 case $stmt{'age'} <= $GLOBALS['third_dun_msg_set']:
158 $dun_message = $GLOBALS['third_dun_msg_text'];
159 break;
160 case $stmt{'age'} <= $GLOBALS['fourth_dun_msg_set']:
161 $dun_message = $GLOBALS['fourth_dun_msg_text'];
162 break;
163 case $stmt{'age'} >= $GLOBALS['fifth_dun_msg_set']:
164 $dun_message = $GLOBALS['fifth_dun_msg_text'];
165 break;
169 // Text only labels
171 $label_addressee = xl('ADDRESSEE');
172 $label_remitto = xl('REMIT TO');
173 $label_chartnum = xl('Chart Number');
174 $label_insinfo = xl('Insurance information on file');
175 $label_totaldue = xl('Total amount due');
176 $label_payby = xl('If paying by');
177 $label_cards = xl('VISA/MC/AMEX/Dis');
178 $label_cardnum = xl('Card');
179 $label_expiry = xl('Exp');
180 $label_sign = xl('Signature');
181 $label_retpay = xl('Return above part with your payment');
182 $label_pgbrk = xl('STATEMENT SUMMARY');
183 $label_visit = xl('Visit Date');
184 $label_desc = xl('Description');
185 $label_amt = xl('Amount');
187 // This is the text for the top part of the page, up to but not
188 // including the detail lines. Some examples of variable fields are:
189 // %s = string with no minimum width
190 // %9s = right-justified string of 9 characters padded with spaces
191 // %-25s = left-justified string of 25 characters padded with spaces
192 // Note that "\n" is a line feed (new line) character.
193 // reformatted to handle i8n by tony
195 $out = sprintf("%-30s %-23s %-s\n",$clinic_name,$stmt['patient'],$stmt['today']);
196 $out .= sprintf("%-30s %s: %-s\n",$clinic_addr,$label_chartnum,$stmt['pid']);
197 $out .= sprintf("%-30s %-s\n",$clinic_csz,$label_insinfo);
198 $out .= sprintf("%-30s %s: %-s\n",null,$label_totaldue,$stmt['amount']);
199 $out .= "\n\n";
200 $out .= sprintf(" %-30s %-s\n",$label_addressee,$label_remitto);
201 $out .= sprintf(" %-30s %s\n",$stmt['to'][0],$remit_name);
202 $out .= sprintf(" %-30s %s\n",$stmt['to'][1],$remit_addr);
203 $out .= sprintf(" %-30s %s\n",$stmt['to'][2],$remit_csz);
205 if($stmt['to'][3]!='')//to avoid double blank lines the if condition is put.
206 $out .= sprintf(" %-32s\n",$stmt['to'][3]);
207 $out .= sprintf("_________________________________________________________________\n");
208 $out .= "\n";
209 $out .= sprintf("%-32s\n",$label_payby.' '.$label_cards);
210 $out .= "\n";
211 $out .= sprintf("%s_____________________ %s______ %s___________________\n",
212 $label_cardnum,$label_expiry,$label_sign);
213 $out .= sprintf("%-20s %s\n",null,$label_retpay);
214 $out .= sprintf("-----------------------------------------------------------------\n");
215 $out .= "\n";
216 $out .= sprintf("_______________________ %s _______________________\n",$label_pgbrk);
217 $out .= "\n";
218 $out .= sprintf("%-11s %-46s %s\n",$label_visit,$label_desc,$label_amt);
219 $out .= "\n";
221 // This must be set to the number of lines generated above.
223 $count = 21;
225 // This generates the detail lines. Again, note that the values must
226 // be specified in the order used.
230 foreach ($stmt['lines'] as $line) {
231 if ($GLOBALS['use_custom_statement']) {
232 $description = substr($line['desc'],0,30);
235 else {
236 $description = $line['desc'];
240 $tmp = substr($description, 0, 14);
241 if ($tmp == 'Procedure 9920' || $tmp == 'Procedure 9921')
242 $description = xl('Office Visit');
245 $dos = $line['dos'];
246 ksort($line['detail']);
248 foreach ($line['detail'] as $dkey => $ddata) {
249 $ddate = substr($dkey, 0, 10);
250 if (preg_match('/^(\d\d\d\d)(\d\d)(\d\d)\s*$/', $ddate, $matches)) {
251 $ddate = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
253 $amount = '';
255 if ($ddata['pmt']) {
256 $amount = sprintf("%.2f", 0 - $ddata['pmt']);
257 $desc = xl('Paid') .' '. $ddate .': '. $ddata['src'].' '. $ddata['insurance_company'];
258 } else if ($ddata['rsn']) {
259 if ($ddata['chg']) {
260 $amount = sprintf("%.2f", $ddata['chg']);
261 $desc = xl('Adj') .' '. $ddate .': ' . $ddata['rsn'].' '. $ddata['insurance_company'];
262 } else {
263 $desc = xl('Note') .' '. $ddate .': '. $ddata['rsn'].' '. $ddata['insurance_company'];
265 } else if ($ddata['chg'] < 0) {
266 $amount = sprintf("%.2f", $ddata['chg']);
267 $desc = xl('Patient Payment');
268 } else {
269 $amount = sprintf("%.2f", $ddata['chg']);
270 $desc = $description;
274 $out .= sprintf("%-10s %-45s%8s\n", $dos, $desc, $amount);
275 $dos = '';
276 ++$count;
280 // This generates blank lines until we are at line 42.
282 while ($count++ < 42) $out .= "\n";
284 // Fixed text labels
285 $label_ptname = xl('Name');
286 $label_today = xl('Date');
287 $label_due = xl('Due');
288 $label_thanks = xl('Thank you for choosing');
289 $label_call = xl('Please call if any of the above information is incorrect');
290 $label_prompt = xl('We appreciate prompt payment of balances due');
291 $label_dept = xl('Billing Department');
293 // This is the bottom portion of the page.
294 $out .= "\n";
295 if(strlen($stmt['bill_note']) !=0 && $GLOBALS['statement_bill_note_print']) {
296 $out .= sprintf("%-46s\n",$stmt['bill_note']);
298 if ($GLOBALS['use_dunning_message']) {
299 $out .= sprintf("%-46s\n",$dun_message);
301 $out .= "\n";
302 $out .= sprintf("%-s: %-25s %-s: %-14s %-s: %8s\n",$label_ptname,$stmt['patient'],
303 $label_today,$stmt['today'],$label_due,$stmt['amount']);
304 $out .= sprintf("__________________________________________________________________\n");
305 $out .= "\n";
306 $out .= sprintf("%-s\n",$label_call);
307 $out .= sprintf("%-s\n",$label_prompt);
308 $out .= "\n";
309 $out .= sprintf("%-s\n",$billing_contact);
310 $out .= sprintf(" %-s\n",$label_dept);
311 $out .= sprintf(" %-s\n",$billing_phone);
312 $out .= "\014"; // this is a form feed
314 return $out;