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