You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
562 lines
20 KiB
562 lines
20 KiB
2 years ago
|
<?php
|
||
|
|
||
|
/**
|
||
|
* checkout_receipt_array.inc.php
|
||
|
*
|
||
|
* This provides a function to build an array of data for printing on a checkout
|
||
|
* receipt. The idea is to support a receipt-printing script that is very easy
|
||
|
* to understand and customize and does not have to be concerned with where the
|
||
|
* data comes from.
|
||
|
*
|
||
|
* LICENSE: This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* as published by the Free Software Foundation; either version 3
|
||
|
* of the License, or (at your option) any later version.
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see
|
||
|
* http://www.gnu.org/licenses/licenses.html#GPL .
|
||
|
*
|
||
|
* @package OpenEMR
|
||
|
* @license http://www.gnu.org/licenses/licenses.html#GPL GNU GPL V3+
|
||
|
* @author Rod Roark <rod@sunsetsystems.com>
|
||
|
* @copyright Copyright (c) 2013-2021 Rod Roark <rod@sunsetsystems.com>
|
||
|
* @link http://www.open-emr.org
|
||
|
*/
|
||
|
|
||
|
// Get a list item's title, translated if appropriate.
|
||
|
function getAdjustTitle($option)
|
||
|
{
|
||
|
$row = sqlQuery(
|
||
|
"SELECT title, notes FROM list_options WHERE " .
|
||
|
"list_id = 'adjreason' AND option_id = ? AND activity = 1",
|
||
|
array($option)
|
||
|
);
|
||
|
if (empty($row['title'])) {
|
||
|
return $option;
|
||
|
}
|
||
|
return xl_list_label($row['title']);
|
||
|
}
|
||
|
|
||
|
// Store a receipt line item.
|
||
|
//
|
||
|
function receiptArrayDetailLine(
|
||
|
&$aReceipt,
|
||
|
$code_type,
|
||
|
$code,
|
||
|
$description,
|
||
|
$quantity,
|
||
|
$charge,
|
||
|
$billtime = '',
|
||
|
$tax = 0,
|
||
|
$chargecat = ''
|
||
|
) {
|
||
|
$adjust = 0;
|
||
|
$adjreason = '';
|
||
|
|
||
|
// This supports Suriname insurers.
|
||
|
// It is set to true when the Customer is set and its notes include "=Ins".
|
||
|
$insurer = false;
|
||
|
if ($chargecat) {
|
||
|
$tmprow = sqlQuery(
|
||
|
"SELECT notes FROM list_options WHERE list_id = 'chargecats' AND " .
|
||
|
"option_id = ? AND activity = 1 AND notes LIKE '%=Ins%' LIMIT 1",
|
||
|
array($chargecat)
|
||
|
);
|
||
|
if (!empty($tmprow['notes'])) {
|
||
|
$insurer = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If an invoice level adjustment, get it into the right column.
|
||
|
if ($code_type === '') {
|
||
|
$adjust = 0 - $charge;
|
||
|
$charge = 0;
|
||
|
} else {
|
||
|
// Otherwise pull out any adjustments matching this line item.
|
||
|
if (!empty($GLOBALS['gbl_checkout_line_adjustments'])) {
|
||
|
// Total and clear matching adjustments in $aReceipt['_adjusts'].
|
||
|
for ($i = 0; $i < count($aReceipt['_adjusts']); ++$i) {
|
||
|
if (
|
||
|
$aReceipt['_adjusts'][$i]['code_type'] == $code_type &&
|
||
|
$aReceipt['_adjusts'][$i]['code'] == $code &&
|
||
|
$aReceipt['_adjusts'][$i]['post_time'] == $billtime
|
||
|
) {
|
||
|
$adjust += $aReceipt['_adjusts'][$i]['adj_amount'];
|
||
|
if ($aReceipt['_adjusts'][$i]['memo']) {
|
||
|
$adjreason = getAdjustTitle($aReceipt['_adjusts'][$i]['memo']);
|
||
|
}
|
||
|
$aReceipt['_adjusts'][$i]['adj_amount'] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$charge = sprintf('%01.2f', $charge);
|
||
|
$total = sprintf('%01.2f', $charge - $adjust);
|
||
|
if (empty($quantity)) {
|
||
|
$quantity = 1;
|
||
|
}
|
||
|
$price = sprintf('%01.4f', $charge / $quantity);
|
||
|
$tmp = sprintf('%01.2f', $price);
|
||
|
if ($price == $tmp) {
|
||
|
$price = $tmp; // converts xx.xx00 to xx.xx.
|
||
|
}
|
||
|
|
||
|
$aReceipt['items'][] = array(
|
||
|
'code_type' => $code_type,
|
||
|
'code' => $code,
|
||
|
'description' => $description,
|
||
|
'price' => $price,
|
||
|
'quantity' => $quantity,
|
||
|
'charge' => $charge,
|
||
|
'adjustment' => sprintf('%01.2f', $adjust),
|
||
|
'adjreason' => $adjreason,
|
||
|
'total' => $total,
|
||
|
'insurer' => $insurer,
|
||
|
'tax' => $tax,
|
||
|
);
|
||
|
|
||
|
$aReceipt['total_price'] = sprintf('%01.2f', $aReceipt['total_price' ] + $price);
|
||
|
$aReceipt['total_quantity'] = sprintf('%01.2f', $aReceipt['total_quantity' ] + $quantity);
|
||
|
$aReceipt['total_charges'] = sprintf('%01.2f', $aReceipt['total_charge' ] + $charge);
|
||
|
$aReceipt['total_adjustments'] = sprintf('%01.2f', $aReceipt['total_adjustments'] + $adjust);
|
||
|
$aReceipt['total_totals'] = sprintf('%01.2f', $aReceipt['total_totals' ] + $total);
|
||
|
}
|
||
|
|
||
|
// Store a receipt payment line.
|
||
|
//
|
||
|
function receiptArrayPaymentLine(&$aReceipt, $paydate, $amount, $description = '', $method = '')
|
||
|
{
|
||
|
$amount = sprintf('%01.2f', $amount);
|
||
|
$aReceipt['payments'][] = array(
|
||
|
'date' => $paydate,
|
||
|
'method' => $method,
|
||
|
'description' => $description,
|
||
|
'amount' => $amount,
|
||
|
);
|
||
|
$aReceipt['total_payments'] += $amount;
|
||
|
}
|
||
|
|
||
|
// Generate a receipt data array from the last-billed invoice for this patient,
|
||
|
// or from the specified encounter.
|
||
|
//
|
||
|
function generateReceiptArray($patient_id, $encounter = 0, $billtime = '')
|
||
|
{
|
||
|
// Get the most recent invoice data or that for the specified encounter.
|
||
|
$query = "SELECT " .
|
||
|
"fe.id, fe.date, fe.encounter, fe.facility_id, fe.invoice_refno, " .
|
||
|
"u.fname, u.mname, u.lname " .
|
||
|
"FROM form_encounter AS fe " .
|
||
|
"LEFT JOIN users AS u ON u.id = fe.provider_id " .
|
||
|
"WHERE fe.pid = ? ";
|
||
|
$binds = array($patient_id);
|
||
|
if ($encounter) {
|
||
|
$query .= "AND encounter = ?";
|
||
|
$binds[] = $encounter;
|
||
|
} else {
|
||
|
$query .= "ORDER BY id DESC LIMIT 1";
|
||
|
}
|
||
|
$ferow = sqlQuery($query, $binds);
|
||
|
if (empty($ferow)) {
|
||
|
die(xlt("This patient has no activity."));
|
||
|
}
|
||
|
$trans_id = $ferow['id'];
|
||
|
$encounter = $ferow['encounter'];
|
||
|
$svcdate = substr($ferow['date'], 0, 10);
|
||
|
$invoice_refno = $ferow['invoice_refno'];
|
||
|
$docname = '';
|
||
|
if (!empty($ferow['fname'])) {
|
||
|
$docname = trim($ferow['fname']);
|
||
|
}
|
||
|
if (!empty($ferow['mname'])) {
|
||
|
if ($docname) {
|
||
|
$docname .= ' ';
|
||
|
}
|
||
|
$docname .= trim($ferow['fname']);
|
||
|
}
|
||
|
if (!empty($ferow['lname'])) {
|
||
|
if ($docname) {
|
||
|
$docname .= ' ';
|
||
|
}
|
||
|
$docname .= trim($ferow['lname']);
|
||
|
}
|
||
|
|
||
|
// Get details for the visit's facility and organization facility.
|
||
|
$frow = getFacility($ferow['facility_id']);
|
||
|
$orgrow = getFacility(0);
|
||
|
|
||
|
$patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code');
|
||
|
|
||
|
// Get text for the logged-in user's name (first middle last).
|
||
|
$username = "UID: " . $_SESSION["authUserID"];
|
||
|
$userrow = sqlQuery(
|
||
|
"SELECT id, username, fname, mname, lname FROM users " .
|
||
|
"WHERE id = ?",
|
||
|
array($_SESSION["authUserID"])
|
||
|
);
|
||
|
if ($userrow['id']) {
|
||
|
if (!empty($userrow['fname'])) {
|
||
|
$username = $userrow['fname'];
|
||
|
}
|
||
|
if (!empty($userrow['mname'])) {
|
||
|
if (!empty($username)) {
|
||
|
$username .= ' ';
|
||
|
}
|
||
|
$username .= $userrow['mname'];
|
||
|
}
|
||
|
if (!empty($userrow['lname'])) {
|
||
|
if (!empty($username)) {
|
||
|
$username .= ' ';
|
||
|
}
|
||
|
$username .= $userrow['lname'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Compute numbers for summary on right side of page.
|
||
|
$head_begbal = get_patient_balance_excluding($patient_id, $encounter);
|
||
|
|
||
|
$query = "SELECT SUM(fee) AS amount FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND activity = 1 AND " .
|
||
|
"code_type != 'COPAY'";
|
||
|
$binds = array($patient_id, $encounter);
|
||
|
if ($billtime) {
|
||
|
$query .= " AND billed = 1 AND bill_date <= ?";
|
||
|
$binds[] = $billtime;
|
||
|
}
|
||
|
$row = sqlQuery($query, $binds);
|
||
|
$head_charges = $row['amount'];
|
||
|
|
||
|
$query = "SELECT SUM(fee) AS amount FROM drug_sales WHERE " .
|
||
|
"pid = ? AND encounter = ?";
|
||
|
$binds = array($patient_id, $encounter);
|
||
|
if ($billtime) {
|
||
|
$query .= " AND billed = 1 AND bill_date <= ?";
|
||
|
$binds[] = $billtime;
|
||
|
}
|
||
|
$row = sqlQuery($query, $binds);
|
||
|
$head_charges += $row['amount'];
|
||
|
|
||
|
$query = "SELECT SUM(pay_amount) AS payments, " .
|
||
|
"SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
|
||
|
"deleted IS NULL AND pid = ? AND encounter = ?";
|
||
|
$binds = array($patient_id, $encounter);
|
||
|
if ($billtime) {
|
||
|
$query .= " AND post_time <= ?";
|
||
|
$binds[] = $billtime;
|
||
|
}
|
||
|
$row = sqlQuery($query, $binds);
|
||
|
$head_charges -= $row['adjustments'];
|
||
|
$head_payments = $row['payments'];
|
||
|
|
||
|
$query = "SELECT SUM(fee) AS amount FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND activity = 1 AND " .
|
||
|
"code_type = 'COPAY'";
|
||
|
$binds = array($patient_id, $encounter);
|
||
|
if ($billtime) {
|
||
|
$query .= " AND billed = 1 AND bill_date <= ?";
|
||
|
$binds[] = $billtime;
|
||
|
}
|
||
|
$row = sqlQuery($query, $binds);
|
||
|
$head_payments -= $row['amount'];
|
||
|
|
||
|
// This is the amount due for the encounter as a whole up to this point.
|
||
|
$encounter_due = $head_charges - $head_payments;
|
||
|
$head_endbal = $head_begbal + $encounter_due;
|
||
|
|
||
|
$aReceipt = array(
|
||
|
'encounter_id' => $encounter,
|
||
|
'encounter_date' => $svcdate,
|
||
|
'invoice_refno' => $invoice_refno,
|
||
|
'patient_id' => $patient_id,
|
||
|
'patient_pubpid' => $patdata['pubpid'],
|
||
|
'patient_fname' => $patdata['fname'],
|
||
|
'patient_mname' => $patdata['mname'],
|
||
|
'patient_lname' => $patdata['lname'],
|
||
|
'patient_street' => $patdata['street'],
|
||
|
'patient_city' => $patdata['city'],
|
||
|
'patient_state' => $patdata['state'],
|
||
|
'patient_zip' => $patdata['postal_code'],
|
||
|
'facility_id' => $frow['id'],
|
||
|
'facility_name' => $frow['name'],
|
||
|
'facility_street' => $frow['street'],
|
||
|
'facility_city' => $frow['city'],
|
||
|
'facility_state' => $frow['state'],
|
||
|
'facility_zip' => $frow['postal_code'],
|
||
|
'facility_phone' => $frow['phone'],
|
||
|
'facility_fax' => $frow['fax'],
|
||
|
'facility_url' => empty($frow['website']) ? '' : $frow['website'],
|
||
|
'organization_name' => $orgrow['name'],
|
||
|
'docname' => $docname,
|
||
|
'username' => $username,
|
||
|
'userlogin' => $userrow['username'],
|
||
|
'starting_balance' => $head_begbal,
|
||
|
'ending_balance' => $head_endbal,
|
||
|
'items' => array(),
|
||
|
'payments' => array(),
|
||
|
'total_price' => 0,
|
||
|
'total_quantity' => 0,
|
||
|
'total_charges' => 0,
|
||
|
'total_adjustments' => 0,
|
||
|
'total_totals' => 0,
|
||
|
'total_payments' => 0,
|
||
|
'checkout_prvbal' => 0, // see calculation at end of this function
|
||
|
'encounter_due' => $encounter_due,
|
||
|
'cashier' => '',
|
||
|
);
|
||
|
|
||
|
// Get timestamp of the previous checkout, if any.
|
||
|
$prevtime = '1900-01-01 00:00:00';
|
||
|
if ($billtime) {
|
||
|
$tmp = sqlQuery(
|
||
|
"(SELECT bill_date FROM billing WHERE pid = ? AND encounter = ? AND activity = 1 AND billed = 1 AND bill_date < ?) " .
|
||
|
"UNION " .
|
||
|
"(SELECT bill_date FROM drug_sales WHERE pid = ? AND encounter = ? AND billed = 1 AND bill_date < ?) " .
|
||
|
"ORDER BY bill_date DESC LIMIT 1",
|
||
|
array($patient_id, $encounter, $billtime, $patient_id, $encounter, $billtime)
|
||
|
);
|
||
|
if (!empty($tmp['bill_date'])) {
|
||
|
$prevtime = $tmp['bill_date'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create array aAdjusts from ar_activity rows for $inv_encounter.
|
||
|
$aReceipt['_adjusts'] = array();
|
||
|
$ares = sqlStatement(
|
||
|
"SELECT " .
|
||
|
"a.payer_type, a.adj_amount, a.memo, a.code_type, a.code, a.post_time, " .
|
||
|
"s.session_id, s.reference, s.check_date " .
|
||
|
"FROM ar_activity AS a " .
|
||
|
"LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
|
||
|
"a.deleted IS NULL AND a.pid = ? AND a.encounter = ? AND " .
|
||
|
"(a.adj_amount != 0 || a.pay_amount = 0)",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
while ($arow = sqlFetchArray($ares)) {
|
||
|
if ($billtime && $arow['post_time'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
$aReceipt['_adjusts'][] = $arow;
|
||
|
}
|
||
|
|
||
|
// Product sales
|
||
|
$inres = sqlStatement(
|
||
|
"SELECT s.sale_id, s.sale_date, s.fee, s.billed, " .
|
||
|
"s.bill_date, s.quantity, s.drug_id, s.selector, s.user, s.chargecat, d.name " .
|
||
|
"FROM drug_sales AS s LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
|
||
|
"WHERE s.pid = ? AND s.encounter = ? " .
|
||
|
"ORDER BY s.sale_id",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
while ($inrow = sqlFetchArray($inres)) {
|
||
|
if ($billtime && $inrow['bill_date'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
$tmpname = $inrow['name'];
|
||
|
if ($tmpname !== $inrow['selector']) {
|
||
|
$tmpname .= ' / ' . $inrow['selector'];
|
||
|
}
|
||
|
$taxrow = sqlQuery(
|
||
|
"SELECT SUM(fee) AS fee FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND code_type = 'TAX' AND activity = 1 AND ndc_info = ?",
|
||
|
array($patient_id, $encounter, 'P:' . $inrow['sale_id'])
|
||
|
);
|
||
|
$tax = $taxrow['fee'];
|
||
|
receiptArrayDetailLine(
|
||
|
$aReceipt,
|
||
|
'PROD',
|
||
|
$inrow['drug_id'],
|
||
|
$tmpname,
|
||
|
$inrow['quantity'],
|
||
|
$inrow['fee'],
|
||
|
$inrow['bill_date'],
|
||
|
$tax,
|
||
|
$inrow['chargecat']
|
||
|
);
|
||
|
if (!empty($inrow['user'])) {
|
||
|
$aReceipt['cashier'] = $inrow['user'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Service items. Use short code description when available.
|
||
|
$inres = sqlStatement(
|
||
|
"SELECT b.*, c.code_text_short, u.username FROM billing AS b " .
|
||
|
"LEFT JOIN code_types AS ct ON ct.ct_key = b.code_type " .
|
||
|
"LEFT JOIN codes AS c ON c.code_type = ct.ct_id AND c.code = b.code AND c.modifier = b.modifier " .
|
||
|
"LEFT JOIN users AS u on u.id = b.user " .
|
||
|
"WHERE " .
|
||
|
"b.pid = ? AND b.encounter = ? AND " .
|
||
|
"b.code_type != 'COPAY' AND b.code_type != 'TAX' AND b.activity = 1 AND " .
|
||
|
"(ct.ct_id IS NULL OR ct.ct_fee = 1 OR ct.ct_diag = 0) " .
|
||
|
"ORDER BY b.id",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
while ($inrow = sqlFetchArray($inres)) {
|
||
|
if ($billtime && $inrow['bill_date'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
$code_text = empty($inrow['code_text_short']) ? $inrow['code_text'] : $inrow['code_text_short'];
|
||
|
$taxrow = sqlQuery(
|
||
|
"SELECT SUM(fee) AS fee FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND code_type = 'TAX' AND activity = 1 AND ndc_info = ?",
|
||
|
array($patient_id, $encounter, 'S:' . $inrow['id'])
|
||
|
);
|
||
|
$tax = $taxrow['fee'];
|
||
|
receiptArrayDetailLine(
|
||
|
$aReceipt,
|
||
|
$inrow['code_type'],
|
||
|
$inrow['code'],
|
||
|
$code_text,
|
||
|
$inrow['units'],
|
||
|
$inrow['fee'],
|
||
|
$inrow['bill_date'],
|
||
|
$tax,
|
||
|
$inrow['chargecat']
|
||
|
);
|
||
|
if (!empty($inrow['username'])) {
|
||
|
$aReceipt['cashier'] = $inrow['username'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Write any adjustments left in the aAdjusts array.
|
||
|
foreach ($aReceipt['_adjusts'] as $arow) {
|
||
|
if ($arow['adj_amount'] == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
if ($billtime && $arow['post_time'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
// $payer = empty($arow['payer_type']) ? 'Pt' : ('Ins' . $arow['payer_type']);
|
||
|
receiptArrayDetailLine(
|
||
|
$aReceipt,
|
||
|
'',
|
||
|
xl('Adjustment'),
|
||
|
getAdjustTitle($arow['memo']),
|
||
|
1,
|
||
|
0 - $arow['adj_amount']
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Tax items.
|
||
|
$inres = sqlStatement(
|
||
|
"SELECT * FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND code_type = 'TAX' AND activity = 1 " .
|
||
|
"ORDER BY id",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
while ($inrow = sqlFetchArray($inres)) {
|
||
|
if ($billtime && $inrow['bill_date'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
receiptArrayDetailLine(
|
||
|
$aReceipt,
|
||
|
$inrow['code_type'],
|
||
|
$inrow['code'],
|
||
|
$inrow['code_text'],
|
||
|
1,
|
||
|
$inrow['fee']
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$payments = 0;
|
||
|
|
||
|
// Get co-pays.
|
||
|
$inres = sqlStatement(
|
||
|
"SELECT fee, code_text, bill_date FROM billing WHERE " .
|
||
|
"pid = ? AND encounter = ? AND " .
|
||
|
"code_type = 'COPAY' AND activity = 1 AND fee != 0 " .
|
||
|
"ORDER BY id",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
while ($inrow = sqlFetchArray($inres)) {
|
||
|
if ($billtime && $inrow['bill_date'] != $billtime) {
|
||
|
continue;
|
||
|
}
|
||
|
$payments -= sprintf('%01.2f', $inrow['fee']);
|
||
|
receiptArrayPaymentLine(
|
||
|
$aReceipt,
|
||
|
$svcdate,
|
||
|
0 - $inrow['fee'],
|
||
|
$inrow['code_text'],
|
||
|
'COPAY'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Get other payments.
|
||
|
$inres = sqlStatement(
|
||
|
"SELECT " .
|
||
|
"a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, a.post_time, " .
|
||
|
"s.payer_id, s.reference, s.check_date, s.deposit_date " .
|
||
|
"FROM ar_activity AS a " .
|
||
|
"LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
|
||
|
"a.deleted IS NULL AND a.pid = ? AND a.encounter = ? AND " .
|
||
|
"a.pay_amount != 0 " .
|
||
|
"ORDER BY a.post_time, s.check_date, a.sequence_no",
|
||
|
array($patient_id, $encounter)
|
||
|
);
|
||
|
$payer = empty($inrow['payer_type']) ? 'Pt' : ('Ins' . $inrow['payer_type']);
|
||
|
while ($inrow = sqlFetchArray($inres)) {
|
||
|
$meth = $inrow['memo'];
|
||
|
if ($billtime && $inrow['post_time'] != $billtime) {
|
||
|
if ($inrow['post_time'] > $billtime || $inrow['post_time'] <= $prevtime) {
|
||
|
continue;
|
||
|
}
|
||
|
// This is the case of payments after the previous checkout and before this checkout.
|
||
|
$meth = xl('Previous');
|
||
|
}
|
||
|
$payments += sprintf('%01.2f', $inrow['pay_amount']);
|
||
|
receiptArrayPaymentLine(
|
||
|
$aReceipt,
|
||
|
$svcdate,
|
||
|
$inrow['pay_amount'],
|
||
|
$payer . ' ' . $inrow['reference'],
|
||
|
$meth
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Previous balance for this checkout is local to the encounter, and is the total balance
|
||
|
// for the encounter up to this time minus total balance for this checkout.
|
||
|
// If there is no $billtime then this should always be zero.
|
||
|
$aReceipt['checkout_prvbal'] = $aReceipt['encounter_due'] - $aReceipt['total_totals'] + $aReceipt['total_payments'];
|
||
|
|
||
|
// Get cashier as the person who did the checkout. If there was no checkout then it will
|
||
|
// remain as the person who entered the Fee Sheet.
|
||
|
$query = "SELECT u.username FROM ar_activity AS a" .
|
||
|
" JOIN users AS u ON u.id = a.post_user" .
|
||
|
" WHERE" .
|
||
|
" a.deleted IS NULL AND a.pid = ? AND a.encounter = ?";
|
||
|
$binds = array($patient_id, $encounter);
|
||
|
if ($billtime) {
|
||
|
$query .= " AND a.post_time = ?";
|
||
|
$binds[] = $billtime;
|
||
|
}
|
||
|
$query .= " ORDER BY a.sequence_no DESC LIMIT 1";
|
||
|
$inrow = sqlQuery($query, $binds);
|
||
|
if (!empty($inrow['username'])) {
|
||
|
$aReceipt['cashier'] = $inrow['username'];
|
||
|
}
|
||
|
|
||
|
return $aReceipt;
|
||
|
}
|
||
|
|
||
|
// Get the array of checkout timestamps for the specified visit.
|
||
|
//
|
||
|
function craGetTimestamps($patient_id, $encounter_id)
|
||
|
{
|
||
|
$ret = array();
|
||
|
$res = sqlStatement(
|
||
|
"(SELECT bill_date FROM billing WHERE pid = ? AND encounter = ? AND activity = 1 AND billed = 1) " .
|
||
|
"UNION " .
|
||
|
"(SELECT bill_date FROM drug_sales WHERE pid = ? AND encounter = ? AND billed = 1) " .
|
||
|
"ORDER BY bill_date",
|
||
|
array($patient_id, $encounter_id, $patient_id, $encounter_id)
|
||
|
);
|
||
|
while ($row = sqlFetchArray($res)) {
|
||
|
$ret[] = $row['bill_date'];
|
||
|
}
|
||
|
return $ret;
|
||
|
}
|