added ending dates of service
[openemr.git] / library / invoice_summary.inc.php
blobc8637170c820addaa753d64425d7ffaf60edb3bb
1 <?php
2 // Copyright (C) 2005 Rod Roark <rod@sunsetsystems.com>
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This returns an associative array keyed on procedure code, representing
10 // all charge items for one invoice. This array's values are themselves
11 // associative arrays having the following keys:
13 // chg - the sum of line items, including adjustments, for the code
14 // bal - the unpaid balance
15 // adj - the (positive) sum of inverted adjustments
16 // ins - the id of the insurance company that was billed
17 // dtl - associative array of details, if requested
19 // Where details are requested, each dtl array is keyed on a string
20 // beginning with a date in yyyy-mm-dd format, or blanks in the case
21 // of the original charge items. The value array is:
23 // pmt - payment amount as a positive number, only for payments
24 // src - check number or other source, only for payments
25 // chg - invoice line item amount amount, only for charges or
26 // adjustments (adjustments may be zero)
27 // rsn - adjustment reason, only for adjustments
29 function get_invoice_summary($trans_id, $with_detail = false) {
30 global $sl_err, $sl_cash_acc;
32 $codes = array();
34 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
35 if ($sl_err) die($sl_err);
36 if (! $chart_id_cash) die("There is no COA entry for cash account '$sl_cash_acc'");
38 // Request all cash entries belonging to the invoice.
39 $atres = SLQuery("select * from acc_trans where trans_id = $trans_id and chart_id = $chart_id_cash");
40 if ($sl_err) die($sl_err);
42 // Deduct payments for each procedure code from the respective balance owed.
43 $keysuffix = 5000;
44 for ($irow = 0; $irow < SLRowCount($atres); ++$irow) {
45 $row = SLGetRow($atres, $irow);
46 $code = strtoupper($row['memo']);
47 $ins_id = $row['project_id'];
48 if (! $code) $code = "Unknown";
49 $amount = $row['amount'];
50 $codes[$code]['bal'] += $amount; // amount is negative for a payment
51 if ($ins_id)
52 $codes[$code]['ins'] = $ins_id;
54 // Add the details if they want 'em.
55 if ($with_detail) {
56 if (! $codes[$code]['dtl']) $codes[$code]['dtl'] = array();
57 $tmpkey = $row['transdate'] . $keysuffix++;
58 $tmp = array();
59 $tmp['pmt'] = 0 - $amount;
60 $tmp['src'] = $row['source'];
61 $codes[$code]['dtl'][$tmpkey] = $tmp;
65 // Request all line items with money or adjustment reasons belonging
66 // to the invoice.
67 $inres = SLQuery("SELECT * FROM invoice WHERE trans_id = $trans_id AND " .
68 "( sellprice != 0 OR description LIKE 'Adjustment%' OR serialnumber = 'Claim' )");
69 if ($sl_err) die($sl_err);
71 // Add charges and adjustments for each procedure code into its total and balance.
72 $keysuffix = 1000;
73 for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
74 $row = SLGetRow($inres, $irow);
75 // $amount = $row['sellprice'];
76 $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
77 $ins_id = $row['project_id'];
79 $code = "Unknown";
80 if ($row['serialnumber'] == 'Claim') {
81 $code = 'Claim';
83 else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) {
84 $code = strtoupper($matches[1]);
86 else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['description'], $matches)) {
87 $code = strtoupper($matches[1]);
90 $codes[$code]['chg'] += $amount;
91 $codes[$code]['bal'] += $amount;
92 if ($amount < 0) $codes[$code]['adj'] -= $amount;
94 if ($ins_id)
95 $codes[$code]['ins'] = $ins_id;
97 // Add the details if they want 'em.
98 if ($with_detail) {
99 if (! $codes[$code]['dtl']) $codes[$code]['dtl'] = array();
100 if (preg_match("/^Adjustment\s*(\S*)\s*(.*)/", $row['description'], $matches)) {
101 $tmpkey = str_pad($matches[1], 10) . $keysuffix++;
102 $tmp = array();
103 $tmp['chg'] = $amount;
104 $tmp['rsn'] = $matches[2];
105 $codes[$code]['dtl'][$tmpkey] = $tmp;
107 else {
108 $tmpkey = " " . $keysuffix++;
109 $tmp = array();
110 $tmp['chg'] = $amount;
111 $codes[$code]['dtl'][$tmpkey] = $tmp;
116 return $codes;
119 // This determines the party from whom payment is currently expected.
120 // Returns: -1=Nobody, 0=Patient, 1=Ins1, 2=Ins2, 3=Ins3.
122 function responsible_party($trans_id) {
123 global $sl_err;
124 $arres = SLQuery("select * from ar where id = $trans_id");
125 if ($sl_err) die($sl_err);
126 $arrow = SLGetRow($arres, 0);
127 if (! $arrow) die(xl("There is no match for invoice id = ") . $trans_id);
128 if ($arrow['paid'] >= $arrow['netamount']) return -1;
129 $insgot = strtolower($arrow['notes']);
130 $insdone = strtolower($arrow['shipvia']);
131 for ($i = 1; $i <= 3; ++$i) {
132 $lcvalue = "ins$i";
133 if (strpos($insgot, $lcvalue) !== false && strpos($insdone, $lcvalue) === false)
134 return $i;
136 return 0;