6 * @author Cristian NAVALICI
7 * @version 1.0 feb 2008
9 * CAN BE RUN ONLY FROM THE INTERFACE
10 * NEEDS GLOBALS.PHP BEFORE
13 require_once('patient.inc');
14 require_once('DBC_Vektis_constants.php');
20 $lines2 = 0; // total records for part 2
21 $lines3 = 0; // total records for part 3
22 $lines4 = 0; // total records for part 4
23 $totalclaim = 0; // total insurance claim
24 $uniqueid = 0; // the id for lines 202,402,etc
25 $arr_database = array(); // array with all the values which will be saved into a table
26 $filename = ''; // filename used to write/read vektis stuff (with full path)
28 //-----------------------------------------------------------------------------
32 * generates the lines for every DBC
37 function vk_main($dbcid) {
38 // set some global variables first
40 $dbcidglobal = (int)$dbcid;
42 global $patientglobal;
43 $patientglobal = what_patient($dbcid);
46 $prev_amount = vk_prev_amount();
49 $lines[] = vk_generate_insurer();
50 //$lines[] = vk_generate_debtor();
51 $lines[] = vk_generate_service();
52 //echo "DBC $dbcid - " .$prev_amount . '<br/>'; // debug
54 //$line6 = vk_generate_closing() . VK_EOF;
56 foreach ( $lines as $ln ) {
63 //-----------------------------------------------------------------------------
65 * INITIALIZATION FUNCTION
67 * must be called BEFORE any other function around here
73 $working_dir = TMPDIR_DBC
. '/vektis';
75 // if it's not there, we'll create it
76 if ( !file_exists($working_dir) ) {
80 // generate the filename and attempt to create it
82 $filen = C112
.date('dmY').'.txt';
83 $filename = TMPDIR_DBC
.'/vektis/'. $filen;
84 $fp = fopen($filename, "wb");
86 global $filepointer, $lines2, $lines3, $lines4, $totalclaim, $uniqueid, $arr_database;
88 $lines2 = 0; $lines3 = 0; $lines4 = 0; $totalclaim = 0; $uniqueid = 0;
89 $arr_database = array();
91 // generate an unique ID for this vektis session
92 $arr_database['cvd_session'] = vk_vektis_session();
96 //-----------------------------------------------------------------------------
98 * FINALIZATION FUNCTION
100 * must be called AFTER any other function around here
107 if ( $filepointer ) fclose($filepointer);
109 global $arr_database;
110 if ( $arr_database ) $_SESSION['arrdb'] = $arr_database;
113 //-----------------------------------------------------------------------------
118 * this appears only one time / generated file (the same as closing line)
123 function vk_generate_preamble() {
124 // 0101 ATTRIBUTE RECORD
127 // 0102 CODE EXTERNAL INTEGRATION MESSAGE
130 // 0103 VERSION NUMBER MESSAGE STANDARD
133 // 0104 SUB-VERSION NUMBER MESSAGE STANDARD
139 // 0106 CODE INFORMATION SYSTEM SOFTWARE VENDOR
142 // 0107 VERSION INDICATION INFORMATION SYSTEM SOFTWARE VENDOR
143 $_107 = str_pad(C107
, 10, ' ', STR_PAD_LEFT
);
146 $_108 = str_repeat('0', 4); // 4 chars empty string
148 // 0109 CODE SERVICE OFFICE
151 // 0110 HEALTHCARE PROVIDER CODE
152 $_110 = str_repeat('0', 8); // 8 chars empty string
155 $_111 = str_repeat('0', 8); // 8 chars empty string
157 // 0112 Instititution code
160 // 0113 IDENTIFYING CODE PAYMENT TO
163 // 0114 START DATE CLAIM PERIOD
164 $_114 = date('Ymd', strtotime(date('Ymd')) - (24 * 3600)); // one day before today
166 // 0115 END DATE CLAIM PERIOD
167 $_115 = date('Ymd'); // today
169 // 0116 INVOICE NUMBER PARTICIPANT
170 $_116 = vk_invoice_number();
171 global $arr_database;
172 $arr_database['cvd_116'] = $_116;
175 $_117 = date('Ymd'); // today
176 $arr_database['cvd_date'] = $_117;
179 // 0118 VAT-IDENTIFICATION NUMBER
180 $_118 = str_repeat(' ', 14); // 14 chars empty string
182 // 0119 CURRENCY CODE
186 $_180 = str_repeat(' ', 193); // 193 chars empty string
188 // concatenate the big string
190 for ( $i = 1 ; $i <= 19 ; $i++
) {
191 $avar = sprintf('_1%02s', $i);
192 $bigline .= $
{$avar};
195 $bigline .= $_180 . "\r\n";
197 vk_write_file($bigline); // this is written just once per file
201 //-----------------------------------------------------------------------------
203 * GENERATE INSURER RECORD
210 function vk_generate_insurer() {
212 // 0201 ATTRIBUTE RECORD
215 // 0202 IDENTIFICATION DETAIL RECORD
216 $_202 = vk_unique_line_record();
218 // 0203 CIVILIAN SERVICE NUMBER (BSN) INSURED
219 $_203 = vk_patientdata('ssn');
222 $_204 = vk_whatinsurance(1);
223 global $arr_database;
224 $arr_database['cvd_uzovi'][] = $_204;
226 // 0205 INSURED NUMBER (REGISTRATION NUMBER, RELATION NUMBER)
227 $_205 = vk_whatinsurance(2);
229 // 0206 PATIENT (IDENTIFICATION) NUMBER
230 $_206 = vk_patientdata('pid');
231 $arr_database['cvd_pid'][] = $_206;
233 // 0207 DATE OF BIRTH INSURED
234 $_207 = vk_patientdata('dob');
236 // 0208 GENDER CODE INSURED
237 $_208 = vk_patientdata('sex');
239 // 0209 NAME CODE/NAME USAGE (01)
240 $_209 = vk_patientdata('namecode_patient');
242 // 0210 NAME INSURED (01)
243 $_210 = vk_patientdata('namepat');
245 // 0211 PREFIX INSURED (01)
246 $_211 = vk_patientdata('pxnamepat');
248 // 0212 NAME CODE/NAME USAGE (02)
249 $_212 = vk_patientdata('namecode_partner');
251 // 0213 NAME INSURED (02)
252 $_213 = vk_patientdata('namepar');
254 // 0214 PREFIX INSURED (02)
255 $_214 = vk_patientdata('pxnamepar');
257 // 0215 INITIALS INSURED
258 $_215 = vk_patientdata('initials');
260 // 0216 NAME CODE/NAME USAGE (03)
261 $_216 = vk_patientdata('nameusage');
263 //0217 POSTAL CODE (HOME ADDRESS) INSURED
264 $_217 = vk_patientdata('postalcode');
266 //0218 FOREIGN POSTAL CODE
267 $_218 = vk_patientdata('foreignpostalcode');
269 // 0219 STREET NUMBER (HOME ADDRESS) INSURED
270 $_219 = vk_patientdata('stnumber');
272 // 0220 STREET NUMBER AFFIX (HOME ADDRESS) INSURED
273 $_220 = vk_patientdata('stnumberaffix');
275 // 0221 COUNTRY CODE INSURED
276 $_221 = vk_patientdata('countrycode');
278 // 0222 DEBTOR NUMBER
279 $_222 = str_pad(C222
, 11, ' ', STR_PAD_LEFT
);
281 // 0223 INDICATION CUSTOMER DECEASED
285 $_280 = str_repeat(' ', 129); // 129 chars empty string
287 // concatenate the big string
289 for ( $i = 1 ; $i <= 23 ; $i++
) {
290 $avar = sprintf('_2%02s', $i);
291 $bigline .= $
{$avar};
292 //echo "LEN $avar " .mb_strlen(${$avar},'UTF-8') . '<br />';
297 // count the total lines
305 //-----------------------------------------------------------------------------
307 * GENERATE DEBTOR RECORD
310 * NOTE: we don't use it yet!
315 function vk_generate_debtor() {
316 //0301 ATTRIBUTE RECORD
319 // the total lenght for this line is 310
320 $line = str_repeat(' ', 308);
322 // count the total lines
326 $bigline = $_301 . $line;
332 //-----------------------------------------------------------------------------
334 * GENERATE SERVICE RECORD
341 function vk_generate_service() {
342 // 0401 ATTRIBUTE RECORD
345 // 0402 IDENTIFICATION DETAIL RECORD
346 $_402 = vk_unique_line_record();
348 // 0403 CIVILIAN SERVICE NUMBER (BSN) INSURED
349 $_403 = vk_patientdata('ssn');
352 $_404 = vk_whatinsurance(1);
354 // 0405 INSURED NUMBER (REGISTRATION NUMBER, RELATION NUMBER)
355 $_405 = vk_whatinsurance(2);
357 // 0406 AUTOMATIC PAYMENT NUMBER
358 $_406 = str_repeat(' ', 15);
360 // 0407 FORWARDING ALLOWED
364 // 0408 INDICATION SERVICE CODE LIST
368 $_409 = vk_claimcode('declaratie');
371 $_410 = vk_dbcdates(1);
374 $_411 = vk_dbcdates(2);
376 // 0412 DBC SERVICE CODE
377 $_412 = vk_claimcode('prestatie');
379 // 0413 NUMBER OF SERVICES PERFORMED
382 // 0414 HEALTHCARE TRAJECTORY NUMBER
383 $_414 = vk_dbcinfo('ztn');
384 global $arr_database, $dbcidglobal;
385 $arr_database['cvd_ztn'][] = $_414;
386 $arr_database['cvd_dbcid'][] = $dbcidglobal; // we save also dbc id for db
388 // 0415 TYPE OF SPECIALIST
391 // 0416 HEALTHCARE PROVIDER CODE
392 $_416 = C112
; // agb code
394 // 0417 CALCULATION PERCENTAGE
397 // 0418 TARIFF DBC/SERVICE (VAT INCL.)
398 $_418 = vk_dbcinfo('tariff');
400 if ( vk_is_overloop_dbc($dbcidglobal) ) {
401 // 0419 DEDUCTION TYPE
404 // 0420 DEDUCTION AMOUNT
405 $dedamo = vk_deduction($dbcidglobal);
406 $_420 = str_pad($dedamo, 8, '0', STR_PAD_LEFT
);
408 // 0419 DEDUCTION TYPE
411 // 0420 DEDUCTION AMOUNT
412 $_420 = str_pad(C420
, 8, '0', STR_PAD_LEFT
);
416 // 0421 AMOUNT CHARGED (VAT INCL.)
417 $_421i = round (((int)$_418 * $_417) / 10000);
418 $_421 = str_pad($_421i, 8, '0', STR_PAD_LEFT
);
420 // 0422 INDICATION DEBIT/CREDIT (01)
423 // 0423 VAT-PERCENTAGE CLAIM AMOUNT
424 $_423 = str_pad(C423
, 4, '0', STR_PAD_LEFT
);
426 // 0424 CLAIM AMOUNT (VAT INCL.)
427 $_424i = $_421i - $dedamo;
428 if ( $_424i < 0 ) $_424i = 0;
429 $arr_database['cvd_tariff'][] = $_424i;
430 $_424 = str_pad($_424i, 8, '0', STR_PAD_LEFT
);
432 // 0425 INDICATION DEBIT/CREDIT (02)
435 // 0426 REFERENCE NUMBER THIS SERVICE RECORD
436 $_426 = vk_invoice_service();
437 $arr_database['cvd_426'][] = $_426;
439 // 0427 REFERENCE NUMBER PRECEDING RELATED SERVICE RECORD
440 $_427 = str_pad(C427
, 20, ' ', STR_PAD_LEFT
);
443 $_480 = str_repeat(' ', 94); // 94 chars empty string
445 // concatenate the big string
447 for ( $i = 1 ; $i <= 27 ; $i++
) {
448 $avar = sprintf('_4%02s', $i);
449 $bigline .= $
{$avar};
454 // count the total lines
455 global $lines4, $totalclaim;
457 $totalclaim +
= $_424i;
463 //-----------------------------------------------------------------------------
468 * NOTE: we don't use it yet!
473 function vk_generate_comment() {
474 //9801 ATTRIBUTE RECORD
477 // the total lenght for this line is 310
478 $line = str_repeat(' ', 308);
480 $bigline = $_9801 . $line;
486 //-----------------------------------------------------------------------------
488 * GENERATE CLOSING RECORD
495 function vk_generate_closing() {
496 global $lines2, $lines3, $lines4, $totalclaim;
498 //9901 ATTRIBUTE RECORD
501 //9902 NUMBER OF INSURED RECORDS
502 $_9902 = str_pad($lines2, 6, '0', STR_PAD_LEFT
);
504 //9903 NUMBER OF DEBTOR RECORDS
505 $_9903 = str_pad($lines3, 6, '0', STR_PAD_LEFT
);
507 //9904 NUMBER OF SERVICE RECORDS
508 $_9904 = str_pad($lines4, 6, '0', STR_PAD_LEFT
);
510 //9905 NUMBER OF COMMENT RECORDS
513 //9906 TOTAL NUMBER OF DETAIL RECORDS
514 $sumrow = (int)($_9902 +
$_9903 +
$_9904 +
$_9905);
515 $_9906 = str_pad($sumrow, 7, '0', STR_PAD_LEFT
);
517 //9907 TOTAL CLAIM AMOUNT
518 $_9907 = str_pad($totalclaim, 11, '0', STR_PAD_LEFT
);
520 //9908 INDICATION DEBIT/CREDIT
524 $_9980 = str_repeat(' ', 265); // 265 chars empty string
526 // concatenate the big string
528 for ( $i = 1 ; $i <= 8 ; $i++
) {
529 $avar = sprintf('_99%02s', $i);
530 $bigline .= $
{$avar};
533 $bigline .= $_9980. "\r\n";
534 vk_write_file($bigline); // this is written just once per file
540 //-----------------------------------------------------------------------------
541 //-----------------------------------------------------------------------------
542 //-----------------------------------------------------------------------------
544 * FIND UZOVI CODE / POLICY NUMBER FOR THIS DBC
546 * @param int $uzflag = 1 returns uzovi code; $uzflag != 1 returns policy code
549 function vk_whatinsurance($uzflag = 1) {
550 global $patientglobal;
551 $insurer = get_insurers_nl($patientglobal, 1);
552 $uzovi = $insurer['pin_provider'];
553 $policy = $insurer['pin_policy'];
561 if ( strlen($policy) > 15 ) $policy = ''; // to prevent string bigger than 15 char (max allowed by vk)
562 $retval = ( $uzflag == 1 ) ?
str_pad($uzovi, 4, '0', STR_PAD_LEFT
) : str_pad($policy, 15, ' ', STR_PAD_LEFT
);
567 //-----------------------------------------------------------------------------
569 * GENERATE INVOICE NUMBER
571 * unique invoice number format YYYYMMDD0001
572 * It permits max 9999 invoice / day !
577 function vk_invoice_number() {
580 // retrieve auxiliary values
581 $rd = mysql_query("SELECT * FROM cl_aux WHERE aux_id = 'vk_0116_invoice'") or die(mysql_error());
582 $rez = mysql_fetch_array($rd);
584 // if date strings are NOT equal, then we must update the date field with today value
585 // and reset the counter (aux_varn) to 0
586 if ( $date !== trim($rez['aux_varc']) ) {
589 // we are in the same day, so we'll use the value from aux_varn (numeric)
590 $current_number = $rez['aux_varn'] +
1;
593 // update the auxiliary tables with the new values
594 $qu = sprintf("UPDATE cl_aux SET aux_varc = '%s', aux_varn = %d WHERE aux_id = 'vk_0116_invoice'", $date, $current_number);
595 mysql_query($qu) or die(mysql_error());
597 $uniqID = $date . str_pad($current_number, 4, '0', STR_PAD_LEFT
);
601 //-----------------------------------------------------------------------------
603 * GENERATE INVOICE NUMBER FOR EVERY DBC (SERVICE)
605 * unique invoice number format 253-0001 (patient id from openemr + unique number)
606 * the last number is kept into auxiliary table
611 function vk_invoice_service() {
612 global $patientglobal;
614 // retrieve auxiliary values
615 $rd = mysql_query("SELECT * FROM cl_aux WHERE aux_id = 'vk_0426_invoice'") or die(mysql_error());
616 $rez = mysql_fetch_array($rd);
618 $uninum = $rez['aux_varn'] +
1;
620 // update the auxiliary tables with the new values
621 $qu = sprintf("UPDATE cl_aux SET aux_varn = %d WHERE aux_id = 'vk_0426_invoice'", $uninum);
622 mysql_query($qu) or die(mysql_error());
624 $invoice_service = sprintf("%s-%04s", $patientglobal, $uninum);
626 // padding as required
627 return str_pad($invoice_service, 20, ' ', STR_PAD_LEFT
);
630 //-----------------------------------------------------------------------------
632 * GENERATE LINE IDENTIFICATION RECORD
634 * unique number for every generated line
635 * begins with 1 and the add 1 unit at a time
640 function vk_unique_line_record() {
643 // add one unit to the global var
644 $uninum = $uniqueid +
1;
646 // update the global var with the new value
649 // padding as required
650 $id = str_pad($uninum, 12, '0', STR_PAD_LEFT
);
656 //-----------------------------------------------------------------------------
660 * returns different informations about patient
661 * it works with multibyte strings, so mb extension must be enabled!
663 * @param string $param
666 function vk_patientdata($param = 'pid') {
667 mb_internal_encoding('UTF-8');
669 global $patientglobal;
670 $pat = getPatientData($patientglobal);
671 $patnl = getPatientDataNL($patientglobal);
674 case 'pid': $retval = str_pad($patientglobal, 11, ' ', STR_PAD_RIGHT
); break;
675 case 'ssn': $retval = ( $pat['ss'] ) ?
str_pad($pat['ss'], 9, '0', STR_PAD_LEFT
) : '999999999'; break;
676 case 'dob': $retval = str_replace('-', '', $pat['DOB']); break;
678 case 'sex': if ( $pat['sex'] == 'Male' ) $retval = 1; else if ( $pat['sex'] == 'Female' ) $retval = 2;
679 else $retval = 1; break;
681 case 'namecode_patient':
682 // there are four codes but we use only 1-3. no 4
683 /*$pname = $patnl['pdn_pxlast'] .' '. $pat['lname']; // patient's name
684 $parname = $patnl['pdn_pxlastpar'] .' '. $patnl['pdn_lastpar']; // partner's name
685 $pname = trim($pname); $parname = trim($parname);
687 if ( $pname && $parname) $code = 3;
688 else if ( $pname && !$parname) $code = 1;
689 else if ( !$pname && $parname ) $code = 2;
695 $inival = mb_strpad($pat['lname'], 25, ' ', STR_PAD_RIGHT
);
696 $retval = mb_strtoupper($inival, 'UTF-8');
699 $inival = str_pad($patnl['pdn_pxlast'], 10, ' ', STR_PAD_RIGHT
);
700 $retval = mb_strtoupper($inival, 'UTF-8');
703 case 'namecode_partner':
704 $par = trim($patnl['pdn_lastpar']);
705 return ( $par ?
2 : 0 );
709 $_209 = 1 ; // for us always 1 otherwise vk_patientdata('namecode_patient');
710 $_212 = vk_patientdata('namecode_partner');
711 $retval = ( $_212 ) ?
3 : 0;
715 $inival = mb_strpad($patnl['pdn_lastpar'], 25, ' ', STR_PAD_RIGHT
);
716 $retval = mb_strtoupper($inival, 'UTF-8');
719 $inival = str_pad($patnl['pdn_pxlastpar'], 10, ' ', STR_PAD_RIGHT
);
720 $retval = mb_strtoupper($inival, 'UTF-8');
724 $ini = trim($patnl['pdn_initials']);
725 $ini_new = ( $ini ) ?
preg_replace('/[^a-zA-Z]*/','', $ini) : '';
726 $retval = str_pad($ini_new, 6, ' ', STR_PAD_RIGHT
);
730 // check for country code
731 $pcode = ( $pat['country_code'] == CNLCODE
) ?
$pat['postal_code'] : '' ;
732 $retval = str_pad($pcode, 6, ' ', STR_PAD_LEFT
);
734 case 'foreignpostalcode':
735 // check for country code
736 $pcode = ( $pat['country_code'] != CNLCODE
) ?
$pat['postal_code'] : '' ;
737 $retval = str_pad($pcode, 9, ' ', STR_PAD_LEFT
);
740 case 'stnumber': $retval = str_pad($patnl['pdn_number'], 5, '0', STR_PAD_LEFT
); break;
741 case 'stnumberaffix': $retval = str_pad($patnl['pdn_addition'], 6, ' ', STR_PAD_LEFT
); break;
744 $ccode = ( $pat['country_code'] != CNLCODE
) ?
$pat['country_code'] : '';
745 $twocode = ( $ccode ) ?
vk_countrycode($ccode) : '';
746 $retval = str_pad($twocode, 2, ' ', STR_PAD_LEFT
);
754 //-----------------------------------------------------------------------------
756 * FIND THE ISOCODE FOR A COUNTRY CODE
758 * the two digits code
760 * @param int $cid - country id
763 function vk_countrycode($cid) {
764 $q = sprintf("SELECT * FROM geo_country_reference WHERE countries_id = %d ", $cid);
765 $r = mysql_query($q);
766 $row = mysql_fetch_array($r);
767 return $row['countries_iso_code_2'];
770 //-----------------------------------------------------------------------------
772 * PRESTATIE CODE TABLE
776 * @param string $flag prestatie - cl_dbc_prestatiecode | declaratie for cl_declaratiecode
779 function vk_claimcode($flag = 'prestatie') {
781 $cdbc = content_diagnose($dbcidglobal);
782 $pcode = $cdbc['ax_pcode'];
783 $cdate = $cdbc['ax_cdate'];
786 case 'prestatie': $retval = str_pad($pcode, 12, ' ', STR_PAD_LEFT
); break;
788 $q = sprintf("SELECT cl_declaratiecode AS cd FROM cl_prestatiecode WHERE cl_dbc_prestatiecode = '%s'
789 AND cl_prestatiecode_begindatum <= '%s' AND cl_prestatiecode_einddatum >= '%s' ", $pcode, $cdate, $cdate);
790 $r = mysql_query($q) or die(mysql_error());
792 if ( $row = mysql_fetch_array($r) ) $retval = str_pad($row['cd'], 6, ' ', STR_PAD_LEFT
);
793 else $retval = str_pad('', 6, ' ', STR_PAD_LEFT
);
800 //-----------------------------------------------------------------------------
804 * return the start/end dates for a DBC
806 * @param int $flag 1-opening date 2-closing date
809 function vk_dbcdates($flag = 1) {
811 $cdbc = content_diagnose($dbcidglobal);
812 $odate = $cdbc['ax_odate'];
813 $cdate = $cdbc['ax_cdate'];
815 // put them in vektis form YYYYMMDD
816 $od = str_replace('-','', $odate);
817 $cd = str_replace('-','', $cdate);
819 return (( $flag == 1 ) ?
$od : $cd);
823 //-----------------------------------------------------------------------------
827 * return different informations about a DBC
829 * @param string $info
832 function vk_dbcinfo($info = 'ztn') {
834 $cdbc = content_diagnose($dbcidglobal);
837 case 'ztn' : $ztn = $cdbc['ax_ztn']; $retval = str_pad($ztn, 20, ' ', STR_PAD_LEFT
); break;
839 $decode = trim(vk_claimcode('declaratie'));
840 $date = trim(vk_dbcdates(2)); // closing date?
842 $q = sprintf("SELECT cl_dbc_tarief FROM cl_dbc_tarief WHERE cl_declaratiecode = '%s'
843 AND cl_dbc_tarief_begindatum <= '%s' AND cl_dbc_tarief_einddatum >= '%s' ", $decode, $date, $date);
844 $r = mysql_query($q) or die(mysql_error());
845 if ( mysql_num_rows($r) ) {
846 $row = mysql_fetch_array($r); $val = $row['cl_dbc_tarief'];
850 $retval = str_pad($val, 8, '0', STR_PAD_LEFT
);
857 //-----------------------------------------------------------------------------
859 * WRITE THE DATA INTO THE FILE
861 * write the provided date into the file
863 * @param string $data
866 function vk_write_file($data) {
868 if ( !$filepointer ) return FALSE;
870 flock($filepointer, LOCK_EX
);
871 fwrite($filepointer, $data);
872 flock($filepointer, LOCK_UN
);
876 //-----------------------------------------------------------------------------
878 * COUNT THE TOTAL NUMBER OF DBC READY FOR VEKTIS GENERATION
880 * @param int $type - the vektis records type (new; old - to be resubmited)
883 function vk_number_ready($type = 1) {
885 case '1': $type = 1; break;
886 case '3': $type = 3; break;
890 $q = sprintf("SELECT COUNT(*) AS c FROM cl_axes WHERE ax_vkstatus = $type ");
892 $r = mysql_query($q) or die(mysql_error());
893 $row = mysql_fetch_array($r);
894 return (int)$row['c'];
897 //-----------------------------------------------------------------------------
899 * RETURN DBCs READY FOR VEKTIS GENERATION
901 * statuses 0 - DBC open, nothing to do
902 * 1 - DBC closed; to be sent to VK
903 * 2 - DBC closed; sent to VK but w/out returning codes
904 * 3 - DBC closed; sent to VK and invalid; to be resubmited
905 * 4 - DBC closed; sent to VK and validated.
906 * @param int $status - what status do you want
909 function vk_vektis_ready($status = 1) {
910 $q = sprintf("SELECT ax_id FROM cl_axes WHERE ax_vkstatus = %d", $status);
911 $r = mysql_query($q) or die(mysql_error());
914 if ( mysql_num_rows($r) ) {
915 while ( $row = mysql_fetch_array($r) ) {
916 $result[] = content_diagnose($row['ax_id']);
926 //-----------------------------------------------------------------------------
928 * GENERATE AN UNIQUE SESSION ID
930 * it's about vektis session - the generating for file stage
931 * an unique number for a moment in time
936 function vk_vektis_session() {
937 return date('dmYHis');
940 //-----------------------------------------------------------------------------
942 * DISPLAY THE GENERATED FILE
948 function vk_display_file() {
951 $link_filename = basename($filename);
952 echo "<p>The file <a href='" .VK_WORKINGLNK
. "$link_filename'>$filename</a> was generated.</p>";
954 $filepointer = @fopen
($filename, "rb");
957 if ( $filepointer ) {
958 while ( !feof($filepointer) ) {
959 $buffer .= fgets($filepointer, 1024);
963 echo "<textarea rows='20' cols='150' wrap='off' readonly>$buffer</textarea>";
966 //-----------------------------------------------------------------------------
968 * COMMIT TO DB THE VEKTIS
970 * save to db the content of the newly generates Vektis file.
975 function vk_db_commit() {
976 $arr_database = $_SESSION['arrdb'];
977 mysql_query("START TRANSACTION");
978 mysql_query("BEGIN");
980 if ( $arr_database ) {
981 $data = date('Y-m-d', strtotime($arr_database['cvd_date']));
982 // prepate the sql insert statements
983 foreach ( $arr_database['cvd_pid'] as $ak => $av ) {
984 $query = sprintf("INSERT INTO cl_vektis_data
994 VALUES ('%s', %d, '%s', '%s', '%s', '%s', %d, '%s', %d)",
995 $arr_database['cvd_session'],
998 $arr_database['cvd_116'],
999 $arr_database['cvd_uzovi'][$ak],
1000 trim($arr_database['cvd_ztn'][$ak]),
1001 $arr_database['cvd_tariff'][$ak],
1002 trim($arr_database['cvd_426'][$ak]),
1003 $arr_database['cvd_dbcid'][$ak]
1006 // saving to the table
1007 mysql_query($query) or die(mysql_error());
1009 //echo '<pre>'.print_r($query, true).'</pre>'; // debug
1012 // marked the DBC's as sent to vektis
1013 foreach ( $arr_database['cvd_dbcid'] as $dbcid) {
1014 $queryupdate = sprintf("UPDATE cl_axes SET ax_vkstatus = 2 WHERE ax_id = %d ", $dbcid);
1015 mysql_query($queryupdate) or die(mysql_error());
1019 mysql_query("COMMIT");
1022 //-----------------------------------------------------------------------------
1024 * PARSE THE UPLOADED FILE
1027 * @param string $file
1028 * @param int $state - 1 for simulation, 2 for real situation
1031 function vk_parse_returning_file($file = '', $state = 1) {
1032 if ( !$file ) return FALSE;
1034 $filepath = realpath($file);
1035 $fp = @fopen
($filepath, "rb");
1037 $_SESSION['vk_retfile'] = $filepath;
1040 while ( !feof($fp) ) {
1041 $buffer = fgets($fp);
1043 // we get the type of line from the first two digits
1044 $f2 = substr($buffer, 0, 2);
1047 $extarr = vk_process_extra($buffer, 1); $com = vk_process_common($buffer, 1);
1048 vk_shows_line($buffer, $extarr, $com, 1, $state);
1051 $extarr = vk_process_extra($buffer, 2); $com = vk_process_common($buffer, 2);
1052 vk_shows_line($buffer, $extarr, $com, 2, $state);
1055 $extarr = vk_process_extra($buffer, 4); $com = vk_process_common($buffer, 4);
1056 vk_shows_line($buffer, $extarr, $com, 4, $state);
1059 $extarr = vk_process_extra($buffer, 99); $com = vk_process_common($buffer, 99);
1060 vk_shows_line($buffer, $extarr, $com, 99);
1069 //-----------------------------------------------------------------------------
1071 * PROCESS EXTRA INFORMATIONS
1073 * process extra informations from every line in returning file
1075 * @param string $line - whole line (sent line + returning info)
1076 * @param int $case - the line type
1079 function vk_process_extra($line = '', $case = 1) {
1080 if ( !$line ) return FALSE;
1082 // the start and len values are taken from the vektis documentation
1085 $start = 310; $len = 44;
1086 $extrastr = mb_substr($line, $start, $len);
1087 $_181 = mb_substr($extrastr, 0, 24);
1088 $_182 = mb_substr($extrastr, 24, 8);
1089 $_196 = mb_substr($extrastr, 32, 4);
1090 $_197 = mb_substr($extrastr, 36, 4);
1091 $_198 = mb_substr($extrastr, 40, 4);
1092 $retarr = array('s181' => $_181, 's182' => $_182, 's196' => $_196, 's197' => $_197, 's198' => $_198);
1095 $start = 310; $len = 12;
1096 $extrastr = mb_substr($line, $start, $len);
1097 $_296 = mb_substr($extrastr, 0, 4);
1098 $_297 = mb_substr($extrastr, 4, 4);
1099 $_298 = mb_substr($extrastr, 8, 4);
1100 $retarr = array('s296' => $_296, 's297' => $_297, 's298' => $_298);
1103 $start = 310; $len = 30;
1104 $extrastr = mb_substr($line, $start, $len);
1105 $_481 = mb_substr($extrastr, 0, 8);
1106 $_482 = mb_substr($extrastr, 8, 1);
1107 $_483 = mb_substr($extrastr, 9, 8);
1108 $_484 = mb_substr($extrastr, 17, 1);
1109 $_496 = mb_substr($extrastr, 18, 4);
1110 $_497 = mb_substr($extrastr, 22, 4);
1111 $_498 = mb_substr($extrastr, 26, 4);
1112 $retarr = array('s481' => $_481, 's482' => $_482, 's483' => $_483, 's484' => $_484, 's496' => $_496, 's497' => $_497, 's498' => $_498);
1115 $start = 45; $len = 12;
1116 $extrastr = mb_substr($line, $start, $len);
1117 $_9909 = mb_substr($extrastr, 0, 11);
1118 $_9910 = mb_substr($extrastr, 11, 1);
1119 $retarr = array('s9909' => $_9909, 's9910' => $_9910);
1121 default : return FALSE;
1129 //-----------------------------------------------------------------------------
1131 * PROCESS COMMON INFORMATIONS
1133 * common informations are the common elements from the file and already saved database
1134 * there are the links between db saved info and returning file
1136 * @param string $line - whole line (sent line + returning info)
1137 * @param int $case - the line type
1140 function vk_process_common($line = '', $case = 1) {
1141 if ( !$line ) return FALSE;
1143 // the start and len values are taken from the vektis documentation
1146 $_116 = mb_substr($line, 80, 12);
1147 $_117 = mb_substr($line, 92, 8);
1148 $retarr = array('s116' => $_116, 's117' => $_117);
1151 $_204 = mb_substr($line, 23, 4);
1152 $_206 = mb_substr($line, 42, 11);
1153 $retarr = array('s204' => $_204, 's206' => $_206);
1156 $_414 = mb_substr($line, 99, 20);
1157 $_418 = mb_substr($line, 136, 8);
1158 $_426 = mb_substr($line, 176, 20);
1159 $retarr = array('s414' => $_414, 's418' => $_418, 's426' => $_426);
1167 //-----------------------------------------------------------------------------
1169 * VALIDATE THE RETURNING FILE
1174 * @param string $errcode
1175 * @return bool|array('valid' => true|false, 'letter' => 'X|T|D|space', 'expl' => explanation, 'code' => code)
1177 function vk_validate_vektis($errcode) {
1178 // if we don't have a retcode, then return valid (aka do nothing)
1179 if ( $errcode == '0000') return array('valid' => TRUE, 'letter' => '', 'expl' => '', 'code' => '');
1181 $earr = vk_error_code($errcode);
1185 switch ( $earr['cvr_content'] ) {
1188 case 'D': $retarr['valid'] = FALSE; break;
1189 default: $retarr['valid'] = TRUE;
1191 $retarr['letter'] = $earr['cvr_content'];
1192 $retarr['expl'] = $earr['cvr_expl'];
1193 $retarr['code'] = $earr['cvr_code'];
1199 //-----------------------------------------------------------------------------
1201 * RETURN THE ERROR DESCRIPTION FOR A CODE
1203 * works with cl_vektis_retcodes table
1205 * @param string $retcode
1208 function vk_error_code($retcode) {
1209 $q = sprintf("SELECT * FROM cl_vektis_retcodes WHERE cvr_code = '%s' ", $retcode);
1210 $r = mysql_query($q) or die(mysql_error());
1211 return mysql_fetch_array($r);
1214 //-----------------------------------------------------------------------------
1216 * SHOWS A LINE FROM THE VALIDATION FILE
1218 * shows the validation result
1219 * if in 'real' mode it saves also into db
1221 * @param string $buffer - whole line
1222 * @param array $extarr - extra fields
1223 * @param array $com - common fields
1224 * @param int $line - line type (e.g. 01, 04, 99)
1225 * @param int $state - 1 simulation, 2 real
1228 function vk_shows_line($buffer, $extarr, $com, $line, $state = 1) {
1232 $e1 = vk_validate_vektis($extarr['s196']);
1233 $e2 = vk_validate_vektis($extarr['s197']);
1234 $e3 = vk_validate_vektis($extarr['s198']);
1237 $e1 = vk_validate_vektis($extarr['s296']);
1238 $e2 = vk_validate_vektis($extarr['s297']);
1239 $e3 = vk_validate_vektis($extarr['s298']);
1242 $e1 = vk_validate_vektis($extarr['s496']);
1243 $e2 = vk_validate_vektis($extarr['s497']);
1244 $e3 = vk_validate_vektis($extarr['s498']);
1247 $lastline = vk_format_msg($extarr, 1);
1252 if ( $line != 99 ) {
1253 if ( !$e1['valid'] ||
!$e2['valid'] ||
!$e3['valid'] ) {
1254 $class = 'vk_error';
1255 $e = array($e1, $e2, $e3);
1256 if ( $state == 2 ) vk_mod_vkstatus($line, $com, $e);
1262 $e1str = ( $e1['expl'] ) ?
vk_format_msg($e1) : '';
1263 $e2str = ( $e2['expl'] ) ?
vk_format_msg($e2) : '';
1264 $e3str = ( $e3['expl'] ) ?
vk_format_msg($e3) : '';
1266 $msgline = ( $lastline ) ?
$lastline : $e1str . $e2str . $e3str;
1267 if ( $lastline ) $class = 'vk_expl';
1268 $shstr = "<div class='vk_nline'>$buffer</div><div class='$class'>$msgline</div>";
1270 // display the built string
1274 //-----------------------------------------------------------------------------
1276 * FORMATS THE MESSAGE FOR RETURNING CODES
1278 * for the last line there is a special format
1280 * @param array $e - all infos about a retcode
1281 * @param bool $lastline - is the last line? (default:false)
1284 function vk_format_msg($e, $lastline = 0) {
1286 $str = "TOTAL ASSIGNED AMOUNT: {$e['s9909']} D/C: {$e['s9910']} <br />";
1288 // common line format
1289 $content = ( $e['letter'] != 'O') ?
$e['letter'] : 'OK';
1290 $str = "CODE: {$e['code']} - {$e['expl']} ($content) <br />";
1296 //-----------------------------------------------------------------------------
1298 * MODIFY THE VEKTIS STATUS
1301 * @param int $line - in what line the error appeared
1302 * @param array $com - common part (sent/returned files)
1303 * @param array $ee - those three array errors
1306 function vk_mod_vkstatus($line, $com, $ee) {
1307 // function of the line, we treat different the errors
1310 foreach ( $ee as $e) {
1311 // for X-T letters on the first level we invalidate all the file
1312 if ( $e['letter'] == 'X' ||
$e['letter'] == 'T' ) {
1313 vk_file_invalidatevektis();
1318 $pid = $com['s206'];
1319 foreach ( $ee as $e) {
1320 // for X-T letters on the first level we invalidate all the file ??
1321 if ( $e['letter'] == 'D' ) {
1322 vk_file_invalidatedbc($pid, 2);
1323 } else if ( $e['letter'] == 'O' ){
1329 foreach ( $ee as $e) {
1330 // for X-T letters on the first level we invalidate all the file ??
1331 if ( $e['letter'] == 'D' ) {
1332 vk_file_invalidatedbc($com, 4); // we send as pid the common elements
1333 } else if ( $e['letter'] == 'O' ){
1338 default: return FALSE;
1343 //-----------------------------------------------------------------------------
1345 * RETURNS SOME FIELDS FROM THE FILE
1347 * 116 - vektis invoice number for all the file
1350 * @param string $var - what field
1351 * @param string $ztn - what ztn to look for (needed only for 426 or so, because there are many lines)
1352 * @return string|bool - the invoice number
1354 function vk_file_getvar($var = '116', $ztn = 0) {
1356 if ( !isset($_SESSION['vk_retfile']) ||
empty($_SESSION['vk_retfile']) ) {
1360 // array that containts lines where are the requested var
1361 $elemarr = array('116' => '01', '426' => '04');
1363 $fp = @fopen
($_SESSION['vk_retfile'], "rb");
1365 while ( !feof($fp) ) {
1366 $buffer = fgets($fp);
1367 // we get the type of line from the first two digits
1368 $f2 = substr($buffer, 0, 2);
1370 // we parse all the lines looking for our line type
1371 if ( $f2 == $elemarr[$var] ) {
1373 if ( $var = '116' ) {
1374 $varfield = mb_substr($buffer, 80, 12);
1377 if ( $var = '426' ) {
1378 // not needed in this moment
1382 } else return FALSE;
1384 return trim($varfield);
1388 //-----------------------------------------------------------------------------
1390 * INVALIDATE ALL VEKTIS FILE
1392 * look for dbcs after unique vektis invoice number
1397 function vk_file_invalidatevektis() {
1398 $inv = vk_file_getvar('116');
1400 $q = sprintf("SELECT * FROM cl_vektis_data WHERE cvd_116 = '%s' ", $inv);
1401 $r = mysql_query($q) or die(mysql_error());
1402 while ( $row = mysql_fetch_array($r) ) {
1403 // 3 - means 'to be resubmitted'
1404 $q2 = sprintf("UPDATE cl_axes SET ax_vkstatus = 3 WHERE ax_id = %d ", $row['cvd_dbcid']);
1405 $r2 = mysql_query($q2) or die(mysql_error());
1409 //-----------------------------------------------------------------------------
1411 * INVALIDATE ALL DBC FROM VEKTIS FILE
1413 * for a specified patient
1415 * @param int $pid - patient id
1416 * @param int $case - what situation? row type 02 or 04 ?
1419 function vk_file_invalidatedbc($pid, $case) {
1422 $inv = vk_file_getvar('116');
1423 $q = sprintf("SELECT * FROM cl_vektis_data WHERE cvd_116 = '%s' AND cvd_pid = %d", $inv, $pid);
1424 } else if ( $case == 4) {
1425 // here we don't need the patient id but we use this var to retrieve the common elements
1426 // so here, $pid means actually $com array
1427 $q = sprintf("SELECT * FROM cl_vektis_data WHERE cvd_426 = '%s' ", trim($pid['s426']));
1430 $r = mysql_query($q) or die(mysql_error());
1431 if ( mysql_num_rows($r) ) {
1432 while ( $row = mysql_fetch_array($r) ) {
1433 // 3 - means 'to be resubmitted'
1434 $q2 = sprintf("UPDATE cl_axes SET ax_vkstatus = 3 WHERE ax_id = %d ", $row['cvd_dbcid']);
1435 $r2 = mysql_query($q2) or die(mysql_error());
1440 //-----------------------------------------------------------------------------
1442 * CHANGE DBC STATUS FROM 'WRONG TO RIGHT'
1444 * wrong means it's 3 (to be resubmitted), right means it's 1 (to be sent)
1449 function vk_dbc_resubmit($dbcid = 0) {
1450 if ( !$dbcid ) return FALSE;
1452 // ax_vkstatus = 3 -> supplementary caution measure
1453 $q = sprintf("UPDATE cl_axes SET ax_vkstatus = 1 WHERE ax_id = %d AND ax_vkstatus = 3 ", $dbcid);
1454 mysql_query($q) or die(mysql_error());
1458 //-----------------------------------------------------------------------------
1460 * CUSTOM FUNCTION TO FIND SPECIAL DBC
1462 * condition: Overloop DBCs (all DBCs with encounters both in 2007 and 2008):
1467 function vk_is_overloop_dbc($dbcid = 0) {
1468 if ( !$dbcid ) return FALSE;
1470 $dbc = content_diagnose($dbcid);
1471 $odate = $dbc['ax_odate'];
1472 $cdate = $dbc['ax_cdate'];
1474 global $patientglobal;
1475 $pid = $patientglobal;
1478 $q1 = mysql_query("SELECT COUNT(*) AS a FROM openemr_postcalendar_events WHERE pc_pid = $pid AND pc_apptstatus = '@'
1479 AND pc_eventDate >= '$odate' AND pc_eventDate <= '2007-12-31' ") or die(mysql_error());
1480 $r1 = mysql_fetch_array($q1);
1481 $enc2007 = $r1['a'];
1485 $q2 = mysql_query("SELECT COUNT(*) AS a FROM openemr_postcalendar_events WHERE pc_pid = $pid
1486 AND pc_apptstatus = '@'
1487 AND pc_eventDate >= '2008-01-01' AND pc_eventDate <= '$cdate' ") or die(mysql_error());
1488 $r2 = mysql_fetch_array($q2);
1489 $enc2008 = $r2['a'];
1494 return ($enc2007 && $enc2008);
1499 //-----------------------------------------------------------------------------
1501 * CUSTOM FUNCTION TO CALCULATE DEDUCTION FOR DBC's
1503 * function of F* codes in 2007 (not 2008!)
1508 function vk_deduction($dbcid = 0) {
1509 global $patientglobal;
1510 $pid = $patientglobal;
1512 $enarr = array( 'F101' => '2090', 'F102' => '20040', 'F103' => '41610', 'F104' => '10160',
1513 'F105' => '6840', 'F106' => '8550' , 'F221' => '4750', 'F151' => '2090',
1514 'F152' => '16150','F153' => '44170', 'F154' => '15290', 'F155' => '9780',
1515 'F156' => '9210', 'F224' => '4940');
1517 foreach ( $enarr as $ek => $ev ) {
1518 $q = mysql_query("SELECT COUNT(*) AS a FROM openemr_postcalendar_events WHERE pc_pid = $pid AND pc_apptstatus = '@' AND pc_eventDate >= '2007-01-01' AND pc_eventDate <= '2007-12-31' AND pc_title LIKE '$ek%'");
1519 $r = mysql_fetch_array($q);
1520 $total_sum +
= $r['a'] * $ev;
1523 $total_sum = round($total_sum);
1529 //-----------------------------------------------------------------------------
1531 * CALCULATE THE TARIFF BEFORE ACTUALLY WRITE TO FILE
1533 * it's used to remove the lines with 0 euros amount
1534 * almost the same code as in generating service line (04)
1537 * @return int value of the DBC in eurocents
1539 function vk_prev_amount($dbcid = 0) {
1540 global $arr_database, $dbcidglobal;
1542 // 0418 TARIFF DBC/SERVICE (VAT INCL.)
1543 $_418 = vk_dbcinfo('tariff');
1546 $dedamo = ( vk_is_overloop_dbc($dbcidglobal) ) ?
vk_deduction($dbcidglobal) : 0 ;
1548 // 0417 CALCULATION PERCENTAGE
1551 // 0421 AMOUNT CHARGED (VAT INCL.)
1552 $_421i = round (((int)$_418 * $_417) / 10000);
1554 // 0424 CLAIM AMOUNT (VAT INCL.)
1555 $_424i = $_421i - $dedamo;
1556 if ( $_424i < 0 ) $_424i = 0;
1562 //-----------------------------------------------------------------------------