From 5f174342ed1f67560cb085953bc692933fd62ed8 Mon Sep 17 00:00:00 2001 From: sunsetsystems Date: Fri, 1 Sep 2006 07:14:25 +0000 Subject: [PATCH] various corrections and improvements to remit processing --- interface/billing/claim_status_codes.php | 24 +++++- interface/billing/sl_eob_process.php | 90 +++++++++++++++----- library/invoice_summary.inc.php | 7 +- library/parse_era.inc.php | 137 ++++++++++++++++++++++++++----- library/sl_eob.inc.php | 21 +++-- 5 files changed, 228 insertions(+), 51 deletions(-) diff --git a/interface/billing/claim_status_codes.php b/interface/billing/claim_status_codes.php index 9fc6d488b..7a016d62e 100644 --- a/interface/billing/claim_status_codes.php +++ b/interface/billing/claim_status_codes.php @@ -1,8 +1,27 @@ 'Processed as Primary', + '2' => 'Processed as Secondary', + '3' => 'Processed as Tertiary', + '4' => 'Denied', + '5' => 'Pended', + '11' => 'Received, but not in process', + '13' => 'Suspended', + '15' => 'Suspended - investigation with field', + '16' => 'Suspended - return with material', + '17' => 'Suspended - review pending', + '19' => 'Processed as Primary, Forwarded to Additional Payer(s)', + '20' => 'Processed as Secondary, Forwarded to Additional Payer(s)', + '21' => 'Processed as Tertiary, Forwarded to Additional Payer(s)', + '22' => 'Reversal of Previous Payment', + '23' => 'Not Our Claim, Forwarded to Additional Payer(s)', + '25' => 'Predetermination Pricing Only - No Payment', + '27' => 'Reviewed' + + /**** + // See http://www.wpc-edi.com/codes + // '0' => 'Cannot provide further status electronically.', '1' => 'For more detailed information, see remittance advice.', '2' => 'More detailed information in letter.', @@ -660,5 +679,6 @@ $claim_status_codes = array( '667' => 'Real-Time requests not supported by the information holder, do not resubmit', '668' => 'Missing Endodontics treatment history and prognosis', '669' => 'Dental service narrative needed.' + ****/ ); ?> \ No newline at end of file diff --git a/interface/billing/sl_eob_process.php b/interface/billing/sl_eob_process.php index 38cea0aec..1267e5b25 100644 --- a/interface/billing/sl_eob_process.php +++ b/interface/billing/sl_eob_process.php @@ -103,8 +103,7 @@ // function era_callback(&$out) { global $encount, $debug, $claim_status_codes, $adjustment_reasons, $remark_codes; - global $invoice_total; - // print_r($out); // debugging + global $invoice_total, $last_code; // Some heading information. if ($encount == 0) { @@ -116,6 +115,7 @@ } } + $last_code = ''; $invoice_total = 0.00; $bgcolor = (++$encount & 1) ? "#ddddff" : "#ffdddd"; list($pid, $encounter, $invnumber) = slInvoiceNumber($out); @@ -139,8 +139,20 @@ } } + $insurance_id = 0; + foreach ($codes as $cdata) { + if ($cdata['ins']) { + $insurance_id = $cdata['ins']; + break; + } + } + // Show the claim status. $csc = $out['claim_status_code']; + $inslabel = 'Ins1'; + if ($csc == '1' || $csc == '19') $inslabel = 'Ins1'; + if ($csc == '2' || $csc == '20') $inslabel = 'Ins2'; + if ($csc == '3' || $csc == '21') $inslabel = 'Ins3'; writeMessageLine($bgcolor, 'infdetail', "Claim status $csc: " . $claim_status_codes[$csc]); @@ -150,12 +162,14 @@ "The following claim is not in our database"); } else { - $insdone = strtolower($arrow['shipvia']); - if (strpos($insdone, 'ins1') !== false) { - $inverror = true; - writeMessageLine($bgcolor, 'errdetail', - "Primary insurance EOB was already posted for the following claim"); - } + // Skip this test. Claims can get multiple CLPs from the same payer! + // + // $insdone = strtolower($arrow['shipvia']); + // if (strpos($insdone, 'ins1') !== false) { + // $inverror = true; + // writeMessageLine($bgcolor, 'errdetail', + // "Primary insurance EOB was already posted for the following claim"); + // } } if ($out['warnings']) { @@ -169,9 +183,10 @@ $patient_name = $arrow['name'] ? $arrow['name'] : ($out['patient_fname'] . ' ' . $out['patient_lname']); + $error = $inverror; + // This loops once for each service item in this claim. foreach ($out['svc'] as $svc) { - $error = $inverror; $prev = $codes[$svc['code']]; // This reports detail lines already on file for this service item. @@ -184,7 +199,14 @@ "EOB charge amount " . $svc['chg'] . " for this code does not match our invoice"); $error = true; } + // Check for duplicate payment. Should not happen. + // + // This is not right. What we want to do is check if we have + // any payments or adjustments from this payer for this service item, + // and produce an error if so. The point is that a duplicated claim + // submission may not give the same results as the original. + /**** foreach ($prev['dtl'] as $dkey => $ddata) { if (! $ddata['pmt']) continue; $ddate = parse_date($dkey); @@ -194,17 +216,43 @@ $error = true; } } + ****/ + // The following replaces the above. + if ((sprintf("%.2f",$prev['chg']) != sprintf("%.2f",$prev['bal']) || + $prev['adj'] != 0) && $inslabel == 'Ins1') + { + writeMessageLine($bgcolor, 'errdetail', + "This service item already has payments and/or adjustments!"); + $error = true; + } + unset($codes[$svc['code']]); } - // Or if the service item is not in our database, show it in red for - // manual resolution. Probably what happened is that the billing was - // "corrected" in OpenEMR after the claim was generated... not good! + // If the service item is not in our database... else { + + /**** writeDetailLine($bgcolor, 'errdetail', $patient_name, $invnumber, $svc['code'], $service_date, '*** UNMATCHED SERVICE ITEM ***', $svc['chg'], ''); $error = true; + ****/ + + // No, this is not an error. Instead, if we are not in error mode + // insert the service item into SL. Then display it (in green if it + // was inserted, or in red if we are in error mode). + $description = 'CPT4:' . $svc['code'] . " Added by $inslabel $production_date"; + if (!$error && !$debug) { + slPostCharge($arrow['id'], $svc['chg'], $service_date, $svc['code'], + $insurance_id, $description, $debug); + $invoice_total += $svc['chg']; + } + $class = $error ? 'errdetail' : 'newdetail'; + writeDetailLine($bgcolor, $class, $patient_name, $invnumber, + $svc['code'], $production_date, $description, + $svc['chg'], ($error ? '' : $invoice_total)); + } $class = $error ? 'errdetail' : 'newdetail'; @@ -239,11 +287,11 @@ if ($svc['paid']) { if (!$error && !$debug) { slPostPayment($arrow['id'], $svc['paid'], $check_date, - 'Ins1/' . $out['check_number'], $svc['code'], $prev['ins'], $debug); + "$inslabel/" . $out['check_number'], $svc['code'], $insurance_id, $debug); $invoice_total -= $svc['paid']; } writeDetailLine($bgcolor, $class, $patient_name, $invnumber, - $svc['code'], $check_date, 'Ins1/' . $out['check_number'] . ' payment', + $svc['code'], $check_date, "$inslabel/" . $out['check_number'] . ' payment', 0 - $svc['paid'], ($error ? '' : $invoice_total)); } @@ -261,7 +309,7 @@ $reason .= sprintf("%.2f", $adj['amount']); if (!$error && !$debug) { slPostAdjustment($arrow['id'], 0, $production_date, - $out['check_number'], $svc['code'], $prev['ins'], + $out['check_number'], $svc['code'], $insurance_id, $reason, $debug); } writeMessageLine($bgcolor, $class, $description . ' ' . @@ -271,8 +319,8 @@ else { if (!$error && !$debug) { slPostAdjustment($arrow['id'], $adj['amount'], $production_date, - $out['check_number'], $svc['code'], $prev['ins'], - 'Ins1 adjust code ' . $adj['reason_code'], $debug); + $out['check_number'], $svc['code'], $insurance_id, + "$inslabel adjust code " . $adj['reason_code'], $debug); $invoice_total -= $adj['amount']; } writeDetailLine($bgcolor, $class, $patient_name, $invnumber, @@ -290,13 +338,15 @@ // Cleanup: If all is well, mark Ins1 done and check for secondary billing. if (!$error && !$debug) { - // Mark Ins1 done. - $query = "UPDATE ar SET shipvia = 'Done: Ins1' WHERE id = " . $arrow['id']; + $shipvia = 'Done: Ins1'; + if ($inslabel != 'Ins1') $shipvia .= ',Ins2'; + if ($inslabel == 'Ins3') $shipvia .= ',Ins3'; + $query = "UPDATE ar SET shipvia = '$shipvia' WHERE id = " . $arrow['id']; SLQuery($query); if ($sl_err) die($sl_err); // Check for secondary insurance. $insgot = strtolower($arrow['notes']); - if (strpos($insgot, 'ins2') !== false) { + if ($inslabel == 'Ins1' && strpos($insgot, 'ins2') !== false) { slSetupSecondary($arrow['id'], $debug); writeMessageLine($bgcolor, 'infdetail', 'This claim is now re-queued for secondary paper billing'); diff --git a/library/invoice_summary.inc.php b/library/invoice_summary.inc.php index 4beaf111e..3039146d6 100644 --- a/library/invoice_summary.inc.php +++ b/library/invoice_summary.inc.php @@ -65,7 +65,7 @@ function get_invoice_summary($trans_id, $with_detail = false) { // Request all line items with money or adjustment reasons belonging // to the invoice. $inres = SLQuery("SELECT * FROM invoice WHERE trans_id = $trans_id AND " . - "( sellprice != 0 OR description LIKE 'Adjustment%' )"); + "( sellprice != 0 OR description LIKE 'Adjustment%' OR serialnumber = 'Claim' )"); if ($sl_err) die($sl_err); // Add charges and adjustments for each procedure code into its total and balance. @@ -76,7 +76,10 @@ function get_invoice_summary($trans_id, $with_detail = false) { $ins_id = $row['project_id']; $code = "Unknown"; - if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) { + if ($row['serialnumber'] == 'Claim') { + $code = 'Claim'; + } + else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) { $code = strtoupper($matches[1]); } else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['description'], $matches)) { diff --git a/library/parse_era.inc.php b/library/parse_era.inc.php index 374400d03..e03746c24 100644 --- a/library/parse_era.inc.php +++ b/library/parse_era.inc.php @@ -58,18 +58,23 @@ function parse_era($filename, $cb) { if ($out['loopid']) return 'Unexpected BPR segment'; $out['check_amount'] = trim($seg[2]); $out['check_date'] = trim($seg[16]); // yyyymmdd + // TBD: BPR04 is a payment method code. } else if ($segid == 'TRN') { if ($out['loopid']) return 'Unexpected TRN segment'; $out['check_number'] = trim($seg[2]); $out['payer_tax_id'] = substr($seg[3], 1); // 9 digits $out['payer_id'] = trim($seg[4]); + // Note: TRN04 further qualifies the paying entity within the + // organization identified by TRN03. } else if ($segid == 'REF' && $seg[1] == 'EV') { if ($out['loopid']) return 'Unexpected REF|EV segment'; } else if ($segid == 'CUR' && ! $out['loopid']) { - // ignore + if ($seg[3] && $seg[3] != 1.0) { + return("We cannot handle foreign currencies!"); + } } else if ($segid == 'REF' && ! $out['loopid']) { // ignore @@ -78,6 +83,9 @@ function parse_era($filename, $cb) { if ($out['loopid']) return 'Unexpected DTM|405 segment'; $out['production_date'] = trim($seg[2]); // yyyymmdd } + // + // Loop 1000A is Payer Information. + // else if ($segid == 'N1' && $seg[1] == 'PR') { if ($out['loopid']) return 'Unexpected N1|PR segment'; $out['loopid'] = '1000A'; @@ -85,6 +93,7 @@ function parse_era($filename, $cb) { } else if ($segid == 'N3' && $out['loopid'] == '1000A') { $out['payer_street'] = trim($seg[1]); + // TBD: N302 may exist as an additional address line. } else if ($segid == 'N4' && $out['loopid'] == '1000A') { $out['payer_city'] = trim($seg[1]); @@ -92,11 +101,15 @@ function parse_era($filename, $cb) { $out['payer_zip'] = trim($seg[3]); } else if ($segid == 'REF' && $out['loopid'] == '1000A') { - // ignore + // Other types of REFs may be given to identify the payer, but we + // ignore them. } else if ($segid == 'PER' && $out['loopid'] == '1000A') { - // ignore + // TBD: Report payer contact information as a note. } + // + // Loop 1000B is Payee Identification. + // else if ($segid == 'N1' && $seg[1] == 'PE') { if ($out['loopid'] != '1000A') return 'Unexpected N1|PE segment'; $out['loopid'] = '1000B'; @@ -112,8 +125,13 @@ function parse_era($filename, $cb) { $out['payee_zip'] = trim($seg[3]); } else if ($segid == 'REF' && $out['loopid'] == '1000B') { - // ignore + // Used to report additional ID numbers. Ignored. } + // + // Loop 2000 provides for logical grouping of claim payment information. + // LX is required if any CLPs are present, but so far we do not care + // about loop 2000 content. + // else if ($segid == 'LX') { if (! $out['loopid']) return 'Unexpected LX segment'; parse_era_2100($out, $cb); @@ -125,6 +143,9 @@ function parse_era($filename, $cb) { else if ($segid == 'TS3' && $out['loopid'] == '2000') { // ignore } + // + // Loop 2100 is Claim Payment Information. The good stuff begins here. + // else if ($segid == 'CLP') { if (! $out['loopid']) return 'Unexpected CLP segment'; parse_era_2100($out, $cb); @@ -146,12 +167,6 @@ function parse_era($filename, $cb) { // The 835 spec calls this the "provider-assigned claim control // number" and notes that it is specifically intended for // identifying the claim in the provider's database. - // - // When this field does not conform to either of our formats, - // it's likely that the claim pre-dates the clinic's OpenEMR - // installation and we should probably just flag it for manual - // posting. A better solution might be tailored for sites - // where A/R was converted from a prior system. $out['our_claim_id'] = trim($seg[1]); // $out['claim_status_code'] = trim($seg[2]); @@ -161,43 +176,85 @@ function parse_era($filename, $cb) { $out['payer_claim_id'] = trim($seg[7]); // payer's claim number } else if ($segid == 'CAS' && $out['loopid'] == '2100') { - // TBD: It is technically valid for adjustments to occur at the claim - // level. I guess we need to create a dummy service item for these. - $out['warnings'] .= "Adjustment at claim level not handled!\n"; + // This is a claim-level adjustment and should be unusual. + // Handle it by creating a dummy zero-charge service item and then + // populating the adjustments into it. + $i = 0; // if present, the dummy service item will be first. + if (!$out['svc'][$i]) { + $out['svc'][$i] = array(); + $out['svc'][$i]['code'] = 'Claim'; + $out['svc'][$i]['mod'] = ''; + $out['svc'][$i]['chg'] = '0'; + $out['svc'][$i]['paid'] = '0'; + $out['svc'][$i]['adj'] = array(); + } + for ($k = 2; $k < 20; $k += 3) { + if (!$seg[$k]) break; + $j = count($out['svc'][$i]['adj']); + $out['svc'][$i]['adj'][$j] = array(); + $out['svc'][$i]['adj'][$j]['group_code'] = $seg[1]; + $out['svc'][$i]['adj'][$j]['reason_code'] = $seg[$k]; + $out['svc'][$i]['adj'][$j]['amount'] = $seg[$k+1]; + } } + // QC = Patient else if ($segid == 'NM1' && $seg[1] == 'QC' && $out['loopid'] == '2100') { $out['patient_lname'] = trim($seg[3]); $out['patient_fname'] = trim($seg[4]); $out['patient_mname'] = trim($seg[5]); $out['patient_member_id'] = trim($seg[9]); } + // IL = Insured or Subscriber else if ($segid == 'NM1' && $seg[1] == 'IL' && $out['loopid'] == '2100') { $out['subscriber_lname'] = trim($seg[3]); $out['subscriber_fname'] = trim($seg[4]); $out['subscriber_mname'] = trim($seg[5]); $out['subscriber_member_id'] = trim($seg[9]); } + // 82 = Rendering Provider else if ($segid == 'NM1' && $seg[1] == '82' && $out['loopid'] == '2100') { $out['provider_lname'] = trim($seg[3]); $out['provider_fname'] = trim($seg[4]); $out['provider_mname'] = trim($seg[5]); $out['provider_member_id'] = trim($seg[9]); } + // 74 = Corrected Insured + // TT = Crossover Carrier (Transfer To another payer) + // PR = Corrected Payer else if ($segid == 'NM1' && $out['loopid'] == '2100') { // $out['warnings'] .= "NM1 segment at claim level ignored.\n"; } else if ($segid == 'MOA' && $out['loopid'] == '2100') { $out['warnings'] .= "MOA segment at claim level ignored.\n"; } + // REF segments may provide various identifying numbers. REF02 is: + // 1L = Group or Policy Number + // 1W = Member Identification Number + // 9A = Repriced Claim Reference Number + // 9C = Adjusted Repriced Claim Reference Number + // A6 = Employee Identification Number + // BB = Authorization Number + // CE = Class of Contract Code + // EA = Medical Record Identification Number + // F8 = Original Reference Number + // G1 = Prior Authorization Number + // G3 = Predetermination of Benefits Identification Number + // IG = Insurance Policy Number + // SY = Social Security Number + // 1A, 1B, 1C, 1D, 1G, 1H, D3, G2 = various rendering provider numbers else if ($segid == 'REF' && $seg[1] == '1W' && $out['loopid'] == '2100') { $out['claim_comment'] = trim($seg[2]); } else if ($segid == 'REF' && $out['loopid'] == '2100') { - // ignore; saw a "REF|EA|X" from Tricare, dunno what that is. + // ignore } else if ($segid == 'DTM' && $seg[1] == '050' && $out['loopid'] == '2100') { $out['claim_date'] = trim($seg[2]); // yyyymmdd } + // 036 = expiration date of coverage + // 050 = date claim received by payer + // 232 = claim statement period start + // 233 = claim statement period end else if ($segid == 'DTM' && $out['loopid'] == '2100') { // ignore? } @@ -205,35 +262,65 @@ function parse_era($filename, $cb) { $out['warnings'] .= 'Claim contact information: ' . $seg[4] . "\n"; } + // For AMT01 see the Amount Qualifier Codes on pages 135-135 of the + // Implementation Guide. AMT is only good for comments and is not + // part of claim balancing. else if ($segid == 'AMT' && $out['loopid'] == '2100') { $out['warnings'] .= "AMT segment at claim level ignored.\n"; } + // For QTY01 see the Quantity Qualifier Codes on pages 137-138 of the + // Implementation Guide. QTY is only good for comments and is not + // part of claim balancing. else if ($segid == 'QTY' && $out['loopid'] == '2100') { $out['warnings'] .= "QTY segment at claim level ignored.\n"; } + // + // Loop 2110 is Service Payment Information. + // else if ($segid == 'SVC') { if (! $out['loopid']) return 'Unexpected SVC segment'; $out['loopid'] = '2110'; $svc = explode('^', $seg[1]); if ($svc[0] != 'HC') return 'SVC segment has unexpected qualifier'; + // TBD: Other qualifiers are possible; see IG pages 140-141. $i = count($out['svc']); $out['svc'][$i] = array(); $out['svc'][$i]['code'] = $svc[1]; + $out['svc'][$i]['mod'] = $svc[2] ? $svc[2] : ''; + // TBD: There may be up to 4 procedure modifiers in $svc[2] thru [5]. $out['svc'][$i]['chg'] = $seg[2]; $out['svc'][$i]['paid'] = $seg[3]; $out['svc'][$i]['adj'] = array(); + + // Note: SVC05, if present, indicates the paid units of service. + // It defaults to 1. + + // Note: In the case of bundling, SVC06 reports the original procedure + // code, there are adjustments of the old procedure codes that zero out + // the original charge amounts, a negative adjustment of the new + // procedure code(s) reflecting the old charges, and other "normal" + // adjustments to these charges. + } + // DTM01 identifies the type of service date: + // 472 = a single date of service + // 150 = service period start + // 151 = service period end else if ($segid == 'DTM' && $out['loopid'] == '2110') { $out['dos'] = trim($seg[2]); // yyyymmdd } else if ($segid == 'CAS' && $out['loopid'] == '2110') { - // There may be multiple adjustments per service item. $i = count($out['svc']) - 1; - $j = count($out['svc'][$i]['adj']); - $out['svc'][$i]['adj'][$j] = array(); - $out['svc'][$i]['adj'][$j]['group_code'] = $seg[1]; - $out['svc'][$i]['adj'][$j]['reason_code'] = $seg[2]; - $out['svc'][$i]['adj'][$j]['amount'] = $seg[3]; + for ($k = 2; $k < 20; $k += 3) { + if (!$seg[$k]) break; + $j = count($out['svc'][$i]['adj']); + $out['svc'][$i]['adj'][$j] = array(); + $out['svc'][$i]['adj'][$j]['group_code'] = $seg[1]; + $out['svc'][$i]['adj'][$j]['reason_code'] = $seg[$k]; + $out['svc'][$i]['adj'][$j]['amount'] = $seg[$k+1]; + // Note: $seg[$k+2] is "quantity". A value here indicates a change to + // the number of units of service. We're ignoring that for now. + } } else if ($segid == 'REF' && $out['loopid'] == '2110') { // ignore @@ -250,8 +337,14 @@ function parse_era($filename, $cb) { $out['warnings'] .= "QTY segment at service level ignored.\n"; } else if ($segid == 'PLB') { - $out['warnings'] .= 'PROVIDER LEVEL ADJUSTMENT (not claim-specific): $' . - sprintf('%.2f', $seg[4]) . "\n"; + // Provider-level adjustments are a General Ledger thing and should not + // alter the A/R for the claim, so we just report them as notes. + for ($k = 3; $k < 15; $k += 2) { + if (!$seg[$k]) break; + $out['warnings'] .= 'PROVIDER LEVEL ADJUSTMENT (not claim-specific): $' . + sprintf('%.2f', $seg[$k+1]) . " with reason code " . $seg[$k] . "\n"; + // Note: For PLB adjustment reason codes see IG pages 165-170. + } } else if ($segid == 'SE') { parse_era_2100($out, $cb); diff --git a/library/sl_eob.inc.php b/library/sl_eob.inc.php index df93602ef..00d839686 100644 --- a/library/sl_eob.inc.php +++ b/library/sl_eob.inc.php @@ -112,10 +112,8 @@ // Insert a row into the invoice table. // - function slAddLineItem($invid, $serialnumber, $amount, $adjdate, $insplan, $reason, $debug) { + function slAddLineItem($invid, $serialnumber, $amount, $insplan, $description, $debug) { global $sl_err, $services_id; - $adjdate = fixDate($adjdate); - $description = "Adjustment $adjdate $reason"; $query = "INSERT INTO invoice ( " . "trans_id, " . "parts_id, " . @@ -170,15 +168,28 @@ function slPostPayment($trans_id, $thispay, $thisdate, $thissrc, $code, $thisins, $debug) { global $chart_id_cash, $chart_id_ar; // Post a payment: add to ar, subtract from cash. - slAddTransaction($trans_id, $chart_id_ar, $thispay, $thisdate, $thissrc, $code, $thisins, $debug); + slAddTransaction($trans_id, $chart_id_ar , $thispay , $thisdate, $thissrc, $code, $thisins, $debug); slAddTransaction($trans_id, $chart_id_cash, 0 - $thispay, $thisdate, $thissrc, $code, $thisins, $debug); slUpdateAR($trans_id, 0, $thispay, $thisdate, $debug); } + function slPostCharge($trans_id, $thisamt, $thisdate, $code, $thisins, $description, $debug) { + global $chart_id_income, $chart_id_ar; + // Post an adjustment: add negative invoice item, add to ar, subtract from income + slAddLineItem($trans_id, $code, $thisamt, $thisins, $description, $debug); + if ($thisamt) { + slAddTransaction($trans_id, $chart_id_ar , 0 - $thisamt, $thisdate, $description, $code, $thisins, $debug); + slAddTransaction($trans_id, $chart_id_income, $thisamt , $thisdate, $description, $code, $thisins, $debug); + slUpdateAR($trans_id, $thisamt, 0, '', $debug); + } + } + function slPostAdjustment($trans_id, $thisadj, $thisdate, $thissrc, $code, $thisins, $reason, $debug) { global $chart_id_income, $chart_id_ar; // Post an adjustment: add negative invoice item, add to ar, subtract from income - slAddLineItem($trans_id, $code, 0 - $thisadj, $thisdate, $thisins, $reason, $debug); + $adjdate = fixDate($thisdate); + $description = "Adjustment $adjdate $reason"; + slAddLineItem($trans_id, $code, 0 - $thisadj, $thisins, $description, $debug); if ($thisadj) { slAddTransaction($trans_id, $chart_id_ar, $thisadj, $thisdate, "InvAdj $thissrc", $code, $thisins, $debug); slAddTransaction($trans_id, $chart_id_income, 0 - $thisadj, $thisdate, "InvAdj $thissrc", $code, $thisins, $debug); -- 2.11.4.GIT