Fixes suggested by Brady related to string escaping.
[openemr.git] / interface / drugs / add_edit_drug.php
blob3f31564adf6fbc0e9e270bcbf345545fdfa80e66
1 <?php
2 // Copyright (C) 2006-2011 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 $sanitize_all_escapes = true;
10 $fake_register_globals = false;
12 require_once("../globals.php");
13 require_once("$srcdir/acl.inc");
14 require_once("drugs.inc.php");
15 require_once("$srcdir/options.inc.php");
16 require_once("$srcdir/formdata.inc.php");
17 require_once("$srcdir/htmlspecialchars.inc.php");
19 $alertmsg = '';
20 $drug_id = $_REQUEST['drug'];
21 $info_msg = "";
22 $tmpl_line_no = 0;
24 if (!acl_check('admin', 'drugs')) die(xlt('Not authorized'));
26 // Format dollars for display.
28 function bucks($amount) {
29 if ($amount) {
30 $amount = sprintf("%.2f", $amount);
31 if ($amount != 0.00) return $amount;
33 return '';
36 // Format a string to be used in a quoted HTML form attribute.
38 function htmlAttr($value) {
39 return htmlspecialchars($value, ENT_QUOTES);
42 // Write a line of data for one template to the form.
44 function writeTemplateLine($selector, $dosage, $period, $quantity, $refills, $prices, $taxrates) {
45 global $tmpl_line_no;
46 ++$tmpl_line_no;
48 echo " <tr>\n";
49 echo " <td class='tmplcell drugsonly'>";
50 echo "<input type='text' name='form_tmpl[$tmpl_line_no][selector]' value='" . htmlAttr($selector) . "' size='8' maxlength='100'>";
51 echo "</td>\n";
52 echo " <td class='tmplcell drugsonly'>";
53 echo "<input type='text' name='form_tmpl[$tmpl_line_no][dosage]' value='" . htmlAttr($dosage) . "' size='6' maxlength='10'>";
54 echo "</td>\n";
55 echo " <td class='tmplcell drugsonly'>";
56 generate_form_field(array(
57 'data_type' => 1,
58 'field_id' => 'tmpl[' . $tmpl_line_no . '][period]',
59 'list_id' => 'drug_interval',
60 'empty_title' => 'SKIP'
61 ), $period);
62 echo "</td>\n";
63 echo " <td class='tmplcell drugsonly'>";
64 echo "<input type='text' name='form_tmpl[$tmpl_line_no][quantity]' value='" . htmlAttr($quantity) . "' size='3' maxlength='7'>";
65 echo "</td>\n";
66 echo " <td class='tmplcell drugsonly'>";
67 echo "<input type='text' name='form_tmpl[$tmpl_line_no][refills]' value='" . htmlAttr($refills) . "' size='3' maxlength='5'>";
68 echo "</td>\n";
69 foreach ($prices as $pricelevel => $price) {
70 echo " <td class='tmplcell'>";
71 echo "<input type='text' name='form_tmpl[$tmpl_line_no][price][" . htmlAttr($pricelevel) . "]' value='" . htmlAttr($price) . "' size='6' maxlength='12'>";
72 echo "</td>\n";
74 $pres = sqlStatement("SELECT option_id FROM list_options " .
75 "WHERE list_id = 'taxrate' ORDER BY seq");
76 while ($prow = sqlFetchArray($pres)) {
77 echo " <td class='tmplcell'>";
78 echo "<input type='checkbox' name='form_tmpl[$tmpl_line_no][taxrate][" . htmlAttr($prow['option_id']) . "]' value='1'";
79 if (strpos(":$taxrates", $prow['option_id']) !== false) echo " checked";
80 echo " /></td>\n";
82 echo " </tr>\n";
85 // Translation for form fields used in SQL queries.
87 function escapedff($name) {
88 return add_escape_custom(trim($_POST[$name]));
90 function numericff($name) {
91 $field = trim($_POST[$name]) + 0;
92 return $field;
95 <html>
96 <head>
97 <?php html_header_show(); ?>
98 <title><?php echo $drug_id ? xlt("Edit") : xlt("Add New"); echo ' ' . xlt('Drug'); ?></title>
99 <link rel="stylesheet" href='<?php echo $css_header ?>' type='text/css'>
101 <style>
102 td { font-size:10pt; }
104 <?php if ($GLOBALS['sell_non_drug_products'] == 2) { ?>
105 .drugsonly { display:none; }
106 <?php } else { ?>
107 .drugsonly { }
108 <?php } ?>
110 <?php if (empty($GLOBALS['ippf_specific'])) { ?>
111 .ippfonly { display:none; }
112 <?php } else { ?>
113 .ippfonly { }
114 <?php } ?>
116 </style>
118 <script type="text/javascript" src="../../library/topdialog.js"></script>
119 <script type="text/javascript" src="../../library/dialog.js"></script>
120 <script type="text/javascript" src="../../library/textformat.js"></script>
122 <script language="JavaScript">
124 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
126 // This is for callback by the find-code popup.
127 // Appends to or erases the current list of related codes.
128 function set_related(codetype, code, selector, codedesc) {
129 var f = document.forms[0];
130 var s = f.form_related_code.value;
131 if (code) {
132 if (s.length > 0) s += ';';
133 s += codetype + ':' + code;
134 } else {
135 s = '';
137 f.form_related_code.value = s;
140 // This invokes the find-code popup.
141 function sel_related() {
142 dlgopen('../patient_file/encounter/find_code_popup.php', '_blank', 500, 400);
145 </script>
147 </head>
149 <body class="body_top">
150 <?php
151 // If we are saving, then save and close the window.
152 // First check for duplicates.
154 if ($_POST['form_save']) {
155 $crow = sqlQuery("SELECT COUNT(*) AS count FROM drugs WHERE " .
156 "name = '" . escapedff('form_name') . "' AND " .
157 "form = '" . escapedff('form_form') . "' AND " .
158 "size = '" . escapedff('form_size') . "' AND " .
159 "unit = '" . escapedff('form_unit') . "' AND " .
160 "route = '" . escapedff('form_route') . "' AND " .
161 "drug_id != ?", array($drug_id));
162 if ($crow['count']) {
163 $alertmsg = addslashes(xl('Cannot add this entry because it already exists!'));
167 if (($_POST['form_save'] || $_POST['form_delete']) && !$alertmsg) {
168 $new_drug = false;
169 if ($drug_id) {
170 if ($_POST['form_save']) { // updating an existing drug
171 sqlStatement("UPDATE drugs SET " .
172 "name = '" . escapedff('form_name') . "', " .
173 "ndc_number = '" . escapedff('form_ndc_number') . "', " .
174 "on_order = '" . escapedff('form_on_order') . "', " .
175 "reorder_point = '" . escapedff('form_reorder_point') . "', " .
176 "max_level = '" . escapedff('form_max_level') . "', " .
177 "form = '" . escapedff('form_form') . "', " .
178 "size = '" . escapedff('form_size') . "', " .
179 "unit = '" . escapedff('form_unit') . "', " .
180 "route = '" . escapedff('form_route') . "', " .
181 "cyp_factor = '" . numericff('form_cyp_factor') . "', " .
182 "related_code = '" . escapedff('form_related_code') . "', " .
183 "allow_multiple = " . (empty($_POST['form_allow_multiple' ]) ? 0 : 1) . ", " .
184 "allow_combining = " . (empty($_POST['form_allow_combining']) ? 0 : 1) . ", " .
185 "active = " . (empty($_POST['form_active']) ? 0 : 1) . " " .
186 "WHERE drug_id = ?", array($drug_id));
187 sqlStatement("DELETE FROM drug_templates WHERE drug_id = ?", array($drug_id));
189 else { // deleting
190 if (acl_check('admin', 'super')) {
191 sqlStatement("DELETE FROM drug_inventory WHERE drug_id = ?", array($drug_id));
192 sqlStatement("DELETE FROM drug_templates WHERE drug_id = ?", array($drug_id));
193 sqlStatement("DELETE FROM drugs WHERE drug_id = ?", array($drug_id));
194 sqlStatement("DELETE FROM prices WHERE pr_id = ? AND pr_selector != ''", array($drug_id));
198 else if ($_POST['form_save']) { // saving a new drug
199 $new_drug = true;
200 $drug_id = sqlInsert("INSERT INTO drugs ( " .
201 "name, ndc_number, on_order, reorder_point, max_level, form, " .
202 "size, unit, route, cyp_factor, related_code, " .
203 "allow_multiple, allow_combining, active " .
204 ") VALUES ( " .
205 "'" . escapedff('form_name') . "', " .
206 "'" . escapedff('form_ndc_number') . "', " .
207 "'" . escapedff('form_on_order') . "', " .
208 "'" . escapedff('form_reorder_point') . "', " .
209 "'" . escapedff('form_max_level') . "', " .
210 "'" . escapedff('form_form') . "', " .
211 "'" . escapedff('form_size') . "', " .
212 "'" . escapedff('form_unit') . "', " .
213 "'" . escapedff('form_route') . "', " .
214 "'" . numericff('form_cyp_factor') . "', " .
215 "'" . escapedff('form_related_code') . "', " .
216 (empty($_POST['form_allow_multiple' ]) ? 0 : 1) . ", " .
217 (empty($_POST['form_allow_combining']) ? 0 : 1) . ", " .
218 (empty($_POST['form_active']) ? 0 : 1) .
219 ")");
222 if ($_POST['form_save'] && $drug_id) {
223 $tmpl = $_POST['form_tmpl'];
224 // If using the simplified drug form, then force the one and only
225 // selector name to be the same as the product name.
226 if ($GLOBALS['sell_non_drug_products'] == 2) {
227 $tmpl["1"]['selector'] = $_POST['form_name'];
229 sqlStatement("DELETE FROM prices WHERE pr_id = ? AND pr_selector != ''", array($drug_id));
230 for ($lino = 1; isset($tmpl["$lino"]['selector']); ++$lino) {
231 $iter = $tmpl["$lino"];
232 $selector = trim($iter['selector']);
233 if ($selector) {
234 $taxrates = "";
235 if (!empty($iter['taxrate'])) {
236 foreach ($iter['taxrate'] as $key => $value) {
237 $taxrates .= "$key:";
240 sqlInsert("INSERT INTO drug_templates ( " .
241 "drug_id, selector, dosage, period, quantity, refills, taxrates " .
242 ") VALUES ( ?, ?, ?, ?, ?, ?, ? )",
243 array($drug_id, $selector, trim($iter['dosage']), trim($iter['period']),
244 trim($iter['quantity']), trim($iter['refills']), $taxrates));
246 // Add prices for this drug ID and selector.
247 foreach ($iter['price'] as $key => $value) {
248 $value = $value + 0;
249 if ($value) {
250 sqlStatement("INSERT INTO prices ( " .
251 "pr_id, pr_selector, pr_level, pr_price ) VALUES ( " .
252 "?, ?, ?, ? )",
253 array($drug_id, $selector, $key, $value));
255 } // end foreach price
256 } // end if selector is present
257 } // end for each selector
258 // Save warehouse-specific mins and maxes for this drug.
259 sqlStatement("DELETE FROM product_warehouse WHERE pw_drug_id = ?", array($drug_id));
260 foreach ($_POST['form_wh_min'] as $whid => $whmin) {
261 $whmin = 0 + $whmin;
262 $whmax = 0 + $_POST['form_wh_max'][$whid];
263 if ($whmin != 0 || $whmax != 0) {
264 sqlStatement("INSERT INTO product_warehouse ( " .
265 "pw_drug_id, pw_warehouse, pw_min_level, pw_max_level ) VALUES ( " .
266 "?, ?, ?, ? )", array($drug_id, $whid, $whmin, $whmax));
269 } // end if saving a drug
271 // Close this window and redisplay the updated list of drugs.
273 echo "<script language='JavaScript'>\n";
274 if ($info_msg) echo " alert('$info_msg');\n";
275 echo " if (opener.refreshme) opener.refreshme();\n";
276 if ($new_drug) {
277 echo " window.location.href='add_edit_lot.php?drug=$drug_id&lot=0'\n";
278 } else {
279 echo " window.close();\n";
281 echo "</script></body></html>\n";
282 exit();
285 if ($drug_id) {
286 $row = sqlQuery("SELECT * FROM drugs WHERE drug_id = ?", array($drug_id));
287 $tres = sqlStatement("SELECT * FROM drug_templates WHERE " .
288 "drug_id = ? ORDER BY selector", array($drug_id));
290 else {
291 $row = array(
292 'name' => '',
293 'active' => '1',
294 'allow_multiple' => '1',
295 'allow_combining' => '',
296 'ndc_number' => '',
297 'on_order' => '0',
298 'reorder_point' => '0',
299 'max_level' => '0',
300 'form' => '',
301 'size' => '',
302 'unit' => '',
303 'route' => '',
304 'cyp_factor' => '',
305 'related_code' => '',
310 <form method='post' name='theform' action='add_edit_drug.php?drug=<?php echo $drug_id; ?>'>
311 <center>
313 <table border='0' width='100%'>
315 <tr>
316 <td valign='top' nowrap><b><?php echo xlt('Name'); ?>:</b></td>
317 <td>
318 <input type='text' size='40' name='form_name' maxlength='80' value='<?php echo htmlAttr($row['name']) ?>' style='width:100%' />
319 </td>
320 </tr>
322 <tr>
323 <td valign='top' nowrap><b><?php echo xlt('Active'); ?>:</b></td>
324 <td>
325 <input type='checkbox' name='form_active' value='1'<?php if ($row['active']) echo ' checked'; ?> />
326 </td>
327 </tr>
329 <tr>
330 <td valign='top' nowrap><b><?php echo xlt('Allow'); ?>:</b></td>
331 <td>
332 <input type='checkbox' name='form_allow_multiple' value='1'<?php if ($row['allow_multiple']) echo ' checked'; ?> />
333 <?php echo xlt('Multiple Lots'); ?> &nbsp;
334 <input type='checkbox' name='form_allow_combining' value='1'<?php if ($row['allow_combining']) echo ' checked'; ?> />
335 <?php echo xlt('Combining Lots'); ?>
336 </td>
337 </tr>
339 <tr>
340 <td valign='top' nowrap><b><?php echo xlt('NDC Number'); ?>:</b></td>
341 <td>
342 <input type='text' size='40' name='form_ndc_number' maxlength='20'
343 value='<?php echo htmlAttr($row['ndc_number']) ?>' style='width:100%'
344 onkeyup='maskkeyup(this,"<?php echo addslashes($GLOBALS['gbl_mask_product_id']); ?>")'
345 onblur='maskblur(this,"<?php echo addslashes($GLOBALS['gbl_mask_product_id']); ?>")'
347 </td>
348 </tr>
350 <tr>
351 <td valign='top' nowrap><b><?php echo xlt('On Order'); ?>:</b></td>
352 <td>
353 <input type='text' size='5' name='form_on_order' maxlength='7' value='<?php echo htmlAttr($row['on_order']) ?>' />
354 </td>
355 </tr>
357 <tr>
358 <td valign='top' nowrap><b><?php echo xlt('Limits'); ?>:</b></td>
359 <td>
360 <table>
361 <tr>
362 <td valign='top' nowrap>&nbsp;</td>
363 <td valign='top' nowrap><?php echo xlt('Global'); ?></td>
364 <?php
365 // One column header per warehouse title.
366 $pwarr = array();
367 $pwres = sqlStatement("SELECT lo.option_id, lo.title, " .
368 "pw.pw_min_level, pw.pw_max_level " .
369 "FROM list_options AS lo " .
370 "LEFT JOIN product_warehouse AS pw ON " .
371 "pw.pw_drug_id = ? AND " .
372 "pw.pw_warehouse = lo.option_id WHERE " .
373 "lo.list_id = 'warehouse' ORDER BY lo.seq, lo.title",
374 array($drug_id));
375 while ($pwrow = sqlFetchArray($pwres)) {
376 $pwarr[] = $pwrow;
377 echo " <td valign='top' nowrap>" .
378 htmlspecialchars($pwrow['title']) . "</td>\n";
381 </tr>
382 <tr>
383 <td valign='top' nowrap><?php echo xlt('Min'); ?>&nbsp;</td>
384 <td valign='top'>
385 <input type='text' size='5' name='form_reorder_point' maxlength='7'
386 value='<?php echo htmlAttr($row['reorder_point']) ?>'
387 title='<?php echo xla('Reorder point, 0 if not applicable'); ?>'
388 />&nbsp;&nbsp;
389 </td>
390 <?php
391 foreach ($pwarr as $pwrow) {
392 echo " <td valign='top'>";
393 echo "<input type='text' name='form_wh_min[" .
394 htmlAttr($pwrow['option_id']) .
395 "]' value='" . (0 + $pwrow['pw_min_level']) . "' size='5' " .
396 "title='" . xla('Warehouse minimum, 0 if not applicable') . "' />";
397 echo "&nbsp;&nbsp;</td>\n";
400 </tr>
401 <tr>
402 <td valign='top' nowrap><?php echo xlt('Max'); ?>&nbsp;</td>
403 <td>
404 <input type='text' size='5' name='form_max_level' maxlength='7'
405 value='<?php echo htmlAttr($row['max_level']) ?>'
406 title='<?php echo xla('Maximum reasonable inventory, 0 if not applicable'); ?>'
408 </td>
409 <?php
410 foreach ($pwarr as $pwrow) {
411 echo " <td valign='top'>";
412 echo "<input type='text' name='form_wh_max[" .
413 htmlspecialchars($pwrow['option_id']) .
414 "]' value='" . (0 + $pwrow['pw_max_level']) . "' size='5' " .
415 "title='" . xla('Warehouse maximum, 0 if not applicable') . "' />";
416 echo "</td>\n";
419 </tr>
420 </table>
421 </td>
422 </tr>
424 <tr class='drugsonly'>
425 <td valign='top' nowrap><b><?php echo xlt('Form'); ?>:</b></td>
426 <td>
427 <?php
428 generate_form_field(array('data_type'=>1,'field_id'=>'form','list_id'=>'drug_form','empty_title'=>'SKIP'), $row['form']);
430 </td>
431 </tr>
433 <tr class='drugsonly'>
434 <td valign='top' nowrap><b><?php echo xlt('Pill Size'); ?>:</b></td>
435 <td>
436 <input type='text' size='5' name='form_size' maxlength='7' value='<?php echo htmlAttr($row['size']) ?>' />
437 </td>
438 </tr>
440 <tr class='drugsonly'>
441 <td valign='top' nowrap><b><?php echo xlt('Units'); ?>:</b></td>
442 <td>
443 <?php
444 generate_form_field(array('data_type'=>1,'field_id'=>'unit','list_id'=>'drug_units','empty_title'=>'SKIP'), $row['unit']);
446 </td>
447 </tr>
449 <tr class='drugsonly'>
450 <td valign='top' nowrap><b><?php echo xlt('Route'); ?>:</b></td>
451 <td>
452 <?php
453 generate_form_field(array('data_type'=>1,'field_id'=>'route','list_id'=>'drug_route','empty_title'=>'SKIP'), $row['route']);
455 </td>
456 </tr>
458 <tr class='ippfonly'>
459 <td valign='top' nowrap><b><?php echo xlt('CYP Factor'); ?>:</b></td>
460 <td>
461 <input type='text' size='10' name='form_cyp_factor' maxlength='20' value='<?php echo htmlAttr($row['cyp_factor']) ?>' />
462 </td>
463 </tr>
465 <tr>
466 <td valign='top' nowrap><b><?php echo xlt('Relate To'); ?>:</b></td>
467 <td>
468 <input type='text' size='50' name='form_related_code'
469 value='<?php echo htmlAttr($row['related_code']) ?>' onclick='sel_related()'
470 title='<?php echo xla('Click to select related code'); ?>'
471 style='width:100%' readonly />
472 </td>
473 </tr>
475 <tr>
476 <td valign='top' nowrap>
477 <b><?php echo $GLOBALS['sell_non_drug_products'] == 2 ? xlt('Fees') : xlt('Templates'); ?>:</b>
478 </td>
479 <td>
480 <table border='0' width='100%'>
481 <tr>
482 <td class='drugsonly'><b><?php echo xlt('Name' ); ?></b></td>
483 <td class='drugsonly'><b><?php echo xlt('Schedule'); ?></b></td>
484 <td class='drugsonly'><b><?php echo xlt('Interval'); ?></b></td>
485 <td class='drugsonly'><b><?php echo xlt('Qty' ); ?></b></td>
486 <td class='drugsonly'><b><?php echo xlt('Refills' ); ?></b></td>
487 <?php
488 // Show a heading for each price level. Also create an array of prices
489 // for new template lines.
490 $emptyPrices = array();
491 $pres = sqlStatement("SELECT option_id, title FROM list_options " .
492 "WHERE list_id = 'pricelevel' ORDER BY seq");
493 while ($prow = sqlFetchArray($pres)) {
494 $emptyPrices[$prow['option_id']] = '';
495 echo " <td><b>" .
496 generate_display_field(array('data_type'=>'1','list_id'=>'pricelevel'), $prow['option_id']) .
497 "</b></td>\n";
499 // Show a heading for each tax rate.
500 $pres = sqlStatement("SELECT option_id, title FROM list_options " .
501 "WHERE list_id = 'taxrate' ORDER BY seq");
502 while ($prow = sqlFetchArray($pres)) {
503 echo " <td><b>" .
504 generate_display_field(array('data_type'=>'1','list_id'=>'taxrate'), $prow['option_id']) .
505 "</b></td>\n";
508 </tr>
509 <?php
510 $blank_lines = $GLOBALS['sell_non_drug_products'] == 2 ? 1 : 3;
511 if ($tres) {
512 while ($trow = sqlFetchArray($tres)) {
513 $blank_lines = $GLOBALS['sell_non_drug_products'] == 2 ? 0 : 1;
514 $selector = $trow['selector'];
515 // Get array of prices.
516 $prices = array();
517 $pres = sqlStatement("SELECT lo.option_id, p.pr_price " .
518 "FROM list_options AS lo LEFT OUTER JOIN prices AS p ON " .
519 "p.pr_id = ? AND p.pr_selector = ? AND " .
520 "p.pr_level = lo.option_id " .
521 "WHERE list_id = 'pricelevel' ORDER BY lo.seq",
522 array($drug_id, $selector));
523 while ($prow = sqlFetchArray($pres)) {
524 $prices[$prow['option_id']] = $prow['pr_price'];
526 writeTemplateLine($selector, $trow['dosage'], $trow['period'],
527 $trow['quantity'], $trow['refills'], $prices, $trow['taxrates']);
530 for ($i = 0; $i < $blank_lines; ++$i) {
531 $selector = $GLOBALS['sell_non_drug_products'] == 2 ? $row['name'] : '';
532 writeTemplateLine($selector, '', '', '', '', $emptyPrices, '');
535 </table>
536 </td>
537 </tr>
539 </table>
542 <input type='submit' name='form_save' value='<?php echo xla('Save'); ?>' />
544 <?php if (acl_check('admin', 'super')) { ?>
545 &nbsp;
546 <input type='submit' name='form_delete' value='<?php echo xla('Delete'); ?>' style='color:red' />
547 <?php } ?>
549 &nbsp;
550 <input type='button' value='<?php echo xla('Cancel'); ?>' onclick='window.close()' />
552 </p>
554 </center>
555 </form>
557 <script language="JavaScript">
558 <?php
559 if ($alertmsg) {
560 echo "alert('" . htmlentities($alertmsg) . "');\n";
563 </script>
565 </body>
566 </html>