forked from openemr/openemr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
billing.inc
259 lines (236 loc) · 9.57 KB
/
billing.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?php
// require_once("{$GLOBALS['srcdir']}/sql.inc");
require_once(dirname(__FILE__) . "/sql.inc");
function getBillingById ($id, $cols = "*")
{
return sqlQuery("select $cols from billing where id='$id' and activity=1 order by date DESC limit 0,1");
}
function getBillingByPid ($pid, $cols = "*")
{
return sqlQuery("select $cols from billing where pid ='$pid' and activity=1 order by date DESC limit 0,1");
}
function getBillingByEncounter ($pid,$encounter, $cols = "code_type, code, code_text")
{
$res = sqlStatement("select $cols from billing where encounter = ? and pid=? and activity=1 order by code_type, date ASC", array($encounter,$pid) );
$all=array();
for($iter=0; $row=sqlFetchArray($res); $iter++)
{
$all[$iter] = $row;
}
return $all;
}
function addBilling($encounter_id, $code_type, $code, $code_text, $pid,
$authorized="0", $provider, $modifier="", $units="", $fee="0.00",
$ndc_info='', $justify='', $billed=0, $notecodes='')
{
$sql = "insert into billing (date, encounter, code_type, code, code_text, " .
"pid, authorized, user, groupname, activity, billed, provider_id, " .
"modifier, units, fee, ndc_info, justify, notecodes) values (" .
"NOW(), ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?)";
return sqlInsert($sql, array($encounter_id,$code_type,$code,$code_text,$pid,$authorized,$_SESSION['authId'],$_SESSION['authProvider'],$billed,$provider,$modifier,$units,$fee,$ndc_info,$justify,$notecodes));
}
function authorizeBilling($id, $authorized = "1")
{
sqlQuery("update billing set authorized = '$authorized' where id = '$id'");
}
function deleteBilling($id)
{
sqlStatement("update billing set activity = 0 where id = '$id'");
}
function clearBilling($id)
{
sqlStatement("update billing set justify = '' where id = '$id'");
}
// This function supports the Billing page (billing_process.php), freeb
// processing (process_bills.php), and initiation of secondary processing
// (sl_eob.inc.php). It is called in the following situations:
//
// * billing_process.php sets bill_time, bill_process, payer and target on
// queueing a claim for freeb processing. Create claims row.
// * billing_process.php sets claim status to 2, and payer, on marking a
// claim as billed without actually generating any billing. Create a
// claims row. In this case bill_process will remain at 0 and process_time
// and process_file will not be set.
// * billing_process.php sets bill_process, payer, target and x12 partner
// before calling gen_x12_837. Create a claims row.
// * billing_process.php sets claim status to 2 (billed), bill_process to 2,
// process_time and process_file after calling gen_x12_837. Claims row
// already exists.
// * process_bills.php sets bill_process to 2, process_time, and process_file
// after invoking freeb to process a claim. Claims row already exists.
// * billing_process.php sets claim status to 2 (billed) after creating
// an electronic freeb batch (hcfa-only with recent changes). Claims
// row already exists.
// * EOB posting updates claim status to mark a payer as done. Claims row
// already exists.
// * EOB posting reopens an encounter for billing a secondary payer. Create
// a claims row.
//
// $newversion should be passed to us to indicate if a new claims row
// is to be generated, otherwise one must already exist. The payer, if
// passed in for the latter case, must match the existing claim.
//
// Currently on the billing page the user can select any of the patient's
// payers. That logic will tailor the payer choices to the encounter date.
//
function updateClaim($newversion, $patient_id, $encounter_id, $payer_id=-1, $payer_type=-1,
$status=-1, $bill_process=-1, $process_file='', $target='', $partner_id=-1,$crossover=0)
{
if (!$newversion) {
$sql = "SELECT * FROM claims WHERE patient_id = '$patient_id' AND " .
"encounter_id = '$encounter_id' AND status > 0 AND status < 4 ";
if ($payer_id >= 0) $sql .= "AND payer_id = '$payer_id' ";
$sql .= "ORDER BY version DESC LIMIT 1";
$row = sqlQuery($sql);
if (!$row) return 0;
if ($payer_id < 0) $payer_id = $row['payer_id'];
if ($status < 0) $status = $row['status'];
if ($bill_process < 0) $bill_process = $row['bill_process'];
if ($partner_id < 0) $partner_id = $row['x12_partner_id'];
if (!$process_file ) $process_file = $row['process_file'];
if (!$target ) $target = $row['target'];
}
$claimset = "";
$billset = "";
if (empty($payer_id) || $payer_id < 0) $payer_id = 0;
if ($status==7) {//$status==7 is the claim denial case.
$claimset .= ", status = '$status'";
}
elseif ($status >= 0) {
$claimset .= ", status = '$status'";
if ($status > 1) {
$billset .= ", billed = 1";
if ($status == 2) $billset .= ", bill_date = NOW()";
} else {
$billset .= ", billed = 0";
}
}
if ($status==7) {//$status==7 is the claim denial case.
$billset .= ", bill_process = '$status'";
}
elseif ($bill_process >= 0) {
$claimset .= ", bill_process = '$bill_process'";
$billset .= ", bill_process = '$bill_process'";
}
if ($status==7) {//$status==7 is the claim denial case.
$claimset .= ", process_file = '$process_file'";//Denial reason code is stored here
}
elseif ($process_file) {
$claimset .= ", process_file = '$process_file', process_time = NOW()";
$billset .= ", process_file = '$process_file', process_date = NOW()";
}
if ($target) {
$claimset .= ", target = '$target'";
$billset .= ", target = '$target'";
}
if ($payer_id >= 0) {
$claimset .= ", payer_id = '$payer_id', payer_type = '$payer_type'";
$billset .= ", payer_id = '$payer_id'";
}
if ($partner_id >= 0) {
$claimset .= ", x12_partner_id = '$partner_id'";
$billset .= ", x12_partner_id = '$partner_id'";
}
if ($billset) {
$billset = substr($billset, 2);
sqlStatement("UPDATE billing SET $billset WHERE " .
"encounter = '$encounter_id' AND pid='$patient_id' AND activity = 1");
}
// If a new claim version is requested, insert its row.
//
if ($newversion) {
/****
$payer_id = ($payer_id < 0) ? $row['payer_id'] : $payer_id;
$bill_process = ($bill_process < 0) ? $row['bill_process'] : $bill_process;
$process_file = ($process_file) ? $row['process_file'] : $process_file;
$target = ($target) ? $row['target'] : $target;
$partner_id = ($partner_id < 0) ? $row['x12_partner_id'] : $partner_id;
$sql = "INSERT INTO claims SET " .
"patient_id = '$patient_id', " .
"encounter_id = '$encounter_id', " .
"bill_time = UNIX_TIMESTAMP(NOW()), " .
"payer_id = '$payer_id', " .
"status = '$status', " .
"payer_type = '" . $row['payer_type'] . "', " .
"bill_process = '$bill_process', " .
"process_time = '" . $row['process_time'] . "', " .
"process_file = '$process_file', " .
"target = '$target', " .
"x12_partner_id = '$partner_id'";
****/
if($crossover<>1)
{
$sql = "INSERT INTO claims SET " .
"patient_id = '$patient_id', " .
"encounter_id = '$encounter_id', " .
"bill_time = NOW() $claimset";
}
else
{//Claim automatic forward case.
$sql = "INSERT INTO claims SET " .
"patient_id = '$patient_id', " .
"encounter_id = '$encounter_id', " .
"bill_time = NOW(), status=$status";
}
sqlStatement($sql);
}
// Otherwise update the existing claim row.
//
else if ($claimset) {
$claimset = substr($claimset, 2);
sqlStatement("UPDATE claims SET $claimset WHERE " .
"patient_id = '$patient_id' AND encounter_id = '$encounter_id' AND " .
// "payer_id = '" . $row['payer_id'] . "' AND " .
"version = '" . $row['version'] . "'");
}
// Whenever a claim is marked billed, update A/R accordingly.
//
if ($status == 2) {
if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) {
if ($payer_type > 0) {
sqlStatement("UPDATE form_encounter SET " .
"last_level_billed = '$payer_type' WHERE " .
"pid = '$patient_id' AND encounter = '$encounter_id'");
}
}
else {
$ws = new WSClaim($patient_id, $encounter_id);
}
}
return 1;
}
// Determine if anything in a visit has been billed.
//
function isEncounterBilled($pid, $encounter) {
$row = sqlQuery("SELECT count(*) AS count FROM billing WHERE " .
"pid = '$pid' AND encounter = '$encounter' AND activity = 1 AND " .
"billed = 1");
$count = $row['count'];
if (!$count) {
$row = sqlQuery("SELECT count(*) AS count FROM drug_sales WHERE " .
"pid = '$pid' AND encounter = '$encounter' AND billed = 1");
$count = $row['count'];
}
return $count ? true : false;
}
// Get the co-pay amount that is effective on the given date.
// Or if no insurance on that date, return -1.
//
function getCopay($patient_id, $encdate) {
$tmp = sqlQuery("SELECT provider, copay FROM insurance_data " .
"WHERE pid = '$patient_id' AND type = 'primary' " .
"AND date <= '$encdate' ORDER BY date DESC LIMIT 1");
if ($tmp['provider']) return sprintf('%01.2f', 0 + $tmp['copay']);
return 0;
}
// Get the total co-pay amount paid by the patient for an encounter
function getPatientCopay($patient_id, $encounter) {
$resMoneyGot = sqlStatement("SELECT sum(pay_amount) as PatientPay FROM ar_activity where ".
"pid = ? and encounter = ? and payer_type=0 and account_code='PCP'",
array($patient_id,$encounter));
//new fees screen copay gives account_code='PCP'
$rowMoneyGot = sqlFetchArray($resMoneyGot);
$Copay=$rowMoneyGot['PatientPay'];
return $Copay*-1;
}
?>