Implement direct message receive and background services manager, take 1.
[openemr.git] / library / classes / WSClaim.class.php
blobcb12362a519756009399ca8a4bf457d97db9f881
1 <?php
3 require_once (dirname(__FILE__) . "/WSWrapper.class.php");
4 include_once (dirname(__FILE__) . "/../sqlconf.php");
5 include_once (dirname(__FILE__) . "/../sql.inc");
6 include_once (dirname(__FILE__) . "/../../includes/config.php");
8 class WSClaim extends WSWrapper{
10 var $patient_id;
11 var $foreign_provider_id;
12 var $foreign_patient_id;
13 var $payer_id;
14 var $encounter;
15 var $foreign_payer_id;
16 var $claim;
17 var $_db;
19 function WSClaim($patient_id, $encounter) {
20 if (!is_numeric($patient_id) && is_numeric($encounter)) return;
22 parent::WSWrapper(null,false);
24 $this->patient_id = $patient_id;
25 $this->encounter = $encounter;
26 $this->claim = null;
27 $this->_db = $GLOBALS['adodb']['db'];
29 if ($this->_config['enabled'] === 2) {
30 return;
33 if ($this->load_claim()) {
34 $function['ezybiz.add_invoice'] = array(new xmlrpcval($this->claim,"struct"));
35 $this->send($function);
37 //print_r($this->claim);
40 ///////////////////////////////////////////////////////////////////////
41 // The remainder is used only for SQL-Ledger support, to be deprecated.
42 ///////////////////////////////////////////////////////////////////////
44 function load_claim() {
45 if (!$this->load_patient_foreign_id() ||
46 !$this->load_payer_foreign_id() ||
47 !$this->load_provider_foreign_id() )
48 return false;
49 $invoice_info = array();
51 // Get encounter date and patient name.
52 $sql = "SELECT e.date AS dosdate, " .
53 "CONCAT(pd.fname,' ',pd.mname,' ',pd.lname) as patient_name " .
54 "FROM form_encounter AS e, patient_data AS pd " .
55 "WHERE " .
56 "e.encounter = '" . $this->encounter . "' AND " .
57 "e.pid = '" . $this->patient_id . "' AND " .
58 "pd.pid = e.pid";
59 $eres = $this->_db->Execute($sql);
60 $dosdate = substr($eres->fields['dosdate'], 0, 10);
62 // Create invoice notes for the new invoice that list the patient's
63 // insurance plans. This is so that when payments are posted, the user
64 // can easily see if a secondary claim needs to be submitted.
66 $insnotes = "";
67 $insno = 0;
68 foreach (array("primary", "secondary", "tertiary") as $instype) {
69 ++$insno;
70 $sql = "SELECT ic.name " .
71 "FROM insurance_data AS id, insurance_companies AS ic WHERE " .
72 "id.pid = " . $this->patient_id . " AND " .
73 "id.type = '$instype' AND " .
74 "id.date <= '$dosdate' AND " .
75 "ic.id = id.provider " .
76 "ORDER BY id.date DESC LIMIT 1";
77 $result = $this->_db->Execute($sql);
78 if ($result && !$result->EOF && $result->fields['name']) {
79 if ($insnotes) $insnotes .= "\n";
80 $insnotes .= "Ins$insno: " . $result->fields['name'];
83 $invoice_info['notes'] = $insnotes;
85 $sql = "SELECT * FROM billing WHERE " .
86 "encounter = '" . $this->encounter . "' AND pid = '" . $this->patient_id .
87 "' AND billed = 1 AND activity != 0 AND authorized = 1";
89 $result = $this->_db->Execute($sql);
91 $invoice_info['salesman'] = $this->foreign_provider_id;
92 $invoice_info['customerid'] = $this->foreign_patient_id;
93 $invoice_info['payer_id'] = $this->foreign_payer_id;
94 $invoice_info['invoicenumber'] = $this->patient_id . "." . $this->encounter;
96 $counter = 0;
97 $total = 0;
98 $patient_info = array();
99 $payer_info = array();
101 while ($result && !$result->EOF) {
103 // All bills should be in the accounting system, and mark-as-cleared
104 // is the only reasonable way to process cash-only patients.
106 $process_date = ($result->fields['process_date'] == null) ?
107 date("m-d-Y") :
108 date("m-d-Y", strtotime($result->fields['process_date']));
110 if ($counter == 0) {
111 //unused but supported by ezybiz, helpful in debugging
112 // actualy the dosdate can be used if you want that as the invoice date
113 $invoice_info['customer'] = $eres->fields['patient_name'];
114 $invoice_info['invoicedate'] = $process_date;
115 $invoice_info['duedate'] = $process_date;
116 $invoice_info['items'] = array();
117 $invoice_info['dosdate'] = date("m-d-Y",strtotime($eres->fields['dosdate']));
120 $tii = array();
121 //This is how we set the line items for the invoice, using codes from our encounter
122 //if ($result->fields['code_type'] == "CPT4" || $result->fields['code_type'] == "HCPCS") {
123 //if( $result->fields['code_type'] != "ICD9" ) {
124 if( $result->fields['code_type'] == "COPAY")
126 $patient_info['payment_amount'] += sprintf("%01.2f",$result->fields['fee']);
128 else
130 $payer_info['payment_amount'] += sprintf("%01.2f",$result->fields['fee']);
133 // New as of 2007-06-21: wherever we put a procedure code in the
134 // invoice, append a colon and the modifier if there is one. This way
135 // we can better match up payments and adjustments with the billing data
136 // in OpenEMR.
137 $codekey = $result->fields['code'];
138 if ($result->fields['modifier']) $codekey .= ':' . $result->fields['modifier'];
140 $tii['maincode'] = $codekey;
141 $tii['itemtext'] = $result->fields['code_type'] . ":" .
142 $codekey . " " . $result->fields['code_text'] . " " .
143 $result->fields['justify'];
145 // New logic that respects units:
146 $units = max(1, intval($result->fields['units']));
147 $amount = sprintf("%01.2f", $result->fields['fee']);
148 $price = $amount / $units;
149 $tmp = sprintf("%01.2f", $price);
150 if (abs($price - $tmp) < 0.000001) $price = $tmp;
151 $tii['qty'] = $units;
152 $tii['price'] = $price;
153 $total += $amount;
155 $tii['glaccountid'] = $this->_config['income_acct'];
156 $invoice_info['items'][] = $tii;
158 $result->MoveNext();
159 $counter++;
162 // I think maybe this info is not used.
164 for($counter = 0; $counter < 2; $counter++)
166 $fee = 0;
167 $billto = 0;
168 if($counter == 0)
170 $fee = $patient_info['payment_amount'];
171 $billto = $this->foreign_patient_id;
173 else
175 $fee = $payer_info['payment_amount'];
176 $billto = $this->foreign_payer_id;
178 $invoice_info["invoiceid$counter"] = $this->patient_id . "000" . $this->encounter;
179 $invoice_info["amount$counter"] = $fee;
180 $invoice_info["invoicenumber$counter"] = $this->patient_id . "000" . $this->encounter;
181 $invoice_info["interest$counter"] = 0;
182 $invoice_info["billtoid$counter"] = $billto;
185 $invoice_info['subtotal'] = sprintf("%01.2f",$total);
186 $invoice_info['total'] = sprintf("%01.2f",$total);
188 $this->claim = $invoice_info;
189 return true;
192 function load_provider_foreign_id() {
193 $sql = "SELECT foreign_id FROM integration_mapping AS im " .
194 "LEFT JOIN billing AS b ON im.local_id = b.provider_id WHERE " .
195 "b.encounter = '" . $this->encounter . "' AND " .
196 "b.pid = '" . $this->patient_id . "' AND im.local_table = 'users' " .
197 "AND im.foreign_table = 'salesman'";
198 $result = $this->_db->Execute($sql);
199 if($result && !$result->EOF) {
200 $this->foreign_provider_id = $result->fields['foreign_id'];
201 return true;
203 else {
204 echo "Provider has not been previously sent to external system or no " .
205 "entry was found for them in the integration mapping, could not " .
206 "send claim. Patient: '" . $this->patient_id . "', Encounter: '" .
207 $this->encounter . "'<br>";
208 return false;
212 function load_patient_foreign_id() {
213 $sql = "SELECT foreign_id from integration_mapping as im LEFT JOIN patient_data as pd on im.local_id=pd.id where pd.pid = '" . $this->patient_id . "' and im.local_table='patient_data' and im.foreign_table='customer'";
214 $result = $this->_db->Execute($sql);
215 if($result && !$result->EOF) {
216 $this->foreign_patient_id = $result->fields['foreign_id'];
217 return true;
219 else {
220 echo "Entry has not been previously sent to external system or no entry was found for them in the integration mapping, could not send claim. Patient: '" . $this->patient_id . "'<br>";
221 return false;
225 function load_payer_foreign_id() {
226 $sql = "SELECT payer_id from billing where encounter = '" . $this->encounter . "' and pid = '" . $this->patient_id . "'";
227 $result = $this->_db->Execute($sql);
228 if($result && !$result->EOF) {
229 $this->payer_id = $result->fields['payer_id'];
231 else {
232 echo "No payer id for this claim could be found";
233 return false;
235 // See comments in globals.php:
236 if ($GLOBALS['insurance_companies_are_not_customers']) {
237 $this->foreign_payer_id = $this->payer_id;
239 else {
240 $sql = "SELECT foreign_id from integration_mapping as im LEFT JOIN billing as b on im.local_id=b.payer_id where b.payer_id = '" . $this->payer_id . "' and im.local_table='insurance_companies' and im.foreign_table='customer'";
241 $result = $this->_db->Execute($sql);
242 if($result && !$result->EOF) {
243 $this->foreign_payer_id = $result->fields['foreign_id'];
245 else {
246 echo "Entry has not been previously sent to external system or no entry was found for them in the integration mapping, could not send claim. Insurance Company: '" . $this->payer_id . "'<br>";
247 return false;
250 return true;
253 } // End class WSClaim