<?php /******************************************************************************* MLInvoice: web-based invoicing application. Copyright (C) 2010-2016 Ere Maijala This program is free software. See attached LICENSE. *******************************************************************************/ /******************************************************************************* MLInvoice: web-pohjainen laskutusohjelma. Copyright (C) 2010-2016 Ere Maijala Tämä ohjelma on vapaa. Lue oheinen LICENSE. *******************************************************************************/ require_once 'sqlfuncs.php'; require_once 'datefuncs.php'; require_once 'miscfuncs.php'; // Get post values or defaults for unspecified values function getPostValues(&$formElements, $primaryKey, $parentKey = FALSE) { $values = []; foreach ($formElements as $elem) { if (in_array($elem['type'], [ '', 'IFORM', 'RESULT', 'BUTTON', 'JSBUTTON', 'DROPDOWNMENU', 'IMAGE', 'ROWSUM', 'NEWLINE', 'LABEL' ])) { $values[$elem['name']] = isset($primaryKey) ? $primaryKey : FALSE; } else { $values[$elem['name']] = getPostRequest($elem['name'], FALSE); if (isset($elem['default']) && ($values[$elem['name']] === FALSE || ($elem['type'] == 'INT' && $values[$elem['name']] === ''))) { $values[$elem['name']] = getFormDefaultValue($elem, $parentKey); } elseif ($elem['type'] == 'INT') { $values[$elem['name']] = str_replace(',', '.', $values[$elem['name']]); } elseif ($elem['type'] == 'LIST' && $values[$elem['name']] === FALSE) { $values[$elem['name']] = ''; } } } return $values; } // Get the default value for the given form element function getFormDefaultValue($elem, $parentKey) { if (!isset($elem['default'])) { return false; } if ($elem['default'] === 'DATE_NOW') { return date($GLOBALS['locDateFormat']); } elseif (strstr($elem['default'], 'DATE_NOW+')) { $atmpValues = explode('+', $elem['default']); return date($GLOBALS['locDateFormat'], mktime(0, 0, 0, date('m'), date('d') + $atmpValues[1], date('Y'))); } elseif (strstr($elem['default'], 'ADD')) { $strQuery = str_replace('_PARENTID_', $parentKey, $elem['listquery']); $intAdd = mysqli_fetch_value(mysqli_query_check($strQuery)); return isset($intAdd) ? $intAdd : 0; } elseif ($elem['default'] === 'POST') { // POST has special treatment in iform return ''; } return $elem['default']; } // Save form data. If primaryKey is not set, add a new record and set it, otherwise update existing record. // Return true on success. // Return false on conflict or a string of missing values if encountered. In these cases, the record is not saved. function saveFormData($table, &$primaryKey, &$formElements, &$values, &$warnings, $parentKeyName = '', $parentKey = false, $onPrint = false) { global $dblink; $missingValues = ''; $strFields = ''; $strInsert = ''; $strUpdateFields = ''; $arrValues = []; if (!isset($primaryKey) || !$primaryKey) unset($values['id']); foreach ($formElements as $elem) { $type = $elem['type']; if (in_array($type, [ '', 'IFORM', 'RESULT', 'BUTTON', 'JSBUTTON', 'DROPDOWNMENU', 'IMAGE', 'ROWSUM', 'NEWLINE', 'LABEL' ]) || (isset($elem['read_only']) && $elem['read_only'])) { continue; } $name = $elem['name']; if (!$elem['allow_null'] && (!isset($values[$name]) || $values[$name] === '')) { if ($missingValues) $missingValues .= ', '; $missingValues .= $elem['label']; continue; } if (isset($values[$name])) { $value = $values[$name]; } else { if (isset($primaryKey) && $primaryKey != 0) { continue; } $value = getFormDefaultValue($elem, $parentKey); } if ($type == 'PASSWD' && !$value) continue; // Don't save empty password if (isset($elem['unique']) && $elem['unique']) { $query = "SELECT * FROM $table WHERE deleted=0 AND $name=?"; $params = [ $value ]; if (isset($primaryKey) && $primaryKey) { $query .= ' AND id!=?'; $params[] = $primaryKey; } $res = mysqli_param_query($query, $params); if (mysqli_fetch_array($res)) { $warnings = sprintf($GLOBALS['locDuplicateValue'], $elem['label']); return false; } } if ($strFields) { $strFields .= ', '; $strInsert .= ', '; $strUpdateFields .= ', '; } $strFields .= $name; $fieldPlaceholder = '?'; switch ($type) { case 'PASSWD' : $fieldPlaceholder = 'md5(?)'; $arrValues[] = $values[$name]; break; case 'INT' : case 'HID_INT' : case 'SECHID_INT' : $arrValues[] = ($value !== '' && $value !== false) ? str_replace(',', '.', $value) : ($elem['allow_null'] ? NULL : 0); break; case 'LIST' : case 'SEARCHLIST' : $arrValues[] = isset($values[$name]) ? ($value !== '' ? str_replace(',', '.', $value) : NULL) : NULL; break; case 'CHECK' : $arrValues[] = $value ? 1 : 0; break; case 'INTDATE' : $arrValues[] = $value ? dateConvDate2DBDate($value) : NULL; break; default : $arrValues[] = $value; } $strInsert .= $fieldPlaceholder; $strUpdateFields .= "$name=$fieldPlaceholder"; } if ($missingValues) return $missingValues; mysqli_query_check('SET AUTOCOMMIT = 0'); mysqli_query_check('BEGIN'); try { // Special case for invoice rows - update product stock balance if (isset($values['invoice_id'])) { $invoiceId = $values['invoice_id']; } else { $res = mysqli_param_query( 'SELECT invoice_id FROM {prefix}invoice_row WHERE id=?', [$primaryKey] ); $invoiceId = mysqli_fetch_value($res); } if ($table == '{prefix}invoice_row' && !isOffer($invoiceId)) { updateProductStockBalance( isset($primaryKey) ? $primaryKey : null, isset($values['product_id']) ? $values['product_id'] : null, $values['pcs'] ); } if (!isset($primaryKey) || !$primaryKey) { if ($parentKeyName) { $strFields .= ", $parentKeyName"; $strInsert .= ', ?'; $arrValues[] = $parentKey; } $strQuery = "INSERT INTO $table ($strFields) VALUES ($strInsert)"; mysqli_param_query($strQuery, $arrValues, 'exception'); $primaryKey = mysqli_insert_id($dblink); } else { // Special case for invoice - update product stock balance for all // invoice rows if the invoice was previously deleted if ($table == '{prefix}invoice' && !isOffer($primaryKey)) { $res = mysqli_param_query( 'SELECT deleted FROM {prefix}invoice WHERE id=?', [$primaryKey] ); if (mysqli_fetch_value($res)) { $res = mysqli_param_query( 'SELECT product_id, pcs FROM {prefix}invoice_row WHERE invoice_id=? AND deleted=0', [$primaryKey] ); while ($row = mysqli_fetch_assoc($res)) { updateProductStockBalance( null, $row['product_id'], $row['pcs'] ); } } } $strQuery = "UPDATE $table SET $strUpdateFields, deleted=0 WHERE id=?"; $arrValues[] = $primaryKey; mysqli_param_query($strQuery, $arrValues, 'exception'); } } catch (Exception $e) { mysqli_query_check('ROLLBACK'); mysqli_query_check('SET AUTOCOMMIT = 1'); die($e->getMessage()); } mysqli_query_check('COMMIT'); mysqli_query_check('SET AUTOCOMMIT = 1'); // Special case for invoices - check for duplicate invoice numbers if ($table == '{prefix}invoice' && isset($values['invoice_no']) && !isOffer($primaryKey) ) { $query = 'SELECT ID FROM {prefix}invoice where deleted=0 AND id!=? AND invoice_no=?'; $params = [ $primaryKey, $values['invoice_no'] ]; if (getSetting('invoice_numbering_per_base')) { $query .= ' AND base_id=?'; $params[] = $values['base_id']; } if (getSetting('invoice_numbering_per_year')) { $query .= ' AND invoice_date >= ' . date('Y') . '0101'; } $res = mysqli_param_query($query, $params); if (mysqli_fetch_assoc($res)) $warnings = $GLOBALS['locInvoiceNumberAlreadyInUse']; } // Special case for invoices - check, according to settings, that the invoice has // an invoice number and a reference number if ($table == '{prefix}invoice' && $onPrint && !isOffer($primaryKey) && (getSetting('invoice_add_number') || getSetting('invoice_add_reference_number')) ) { mysqli_query_check( 'LOCK TABLES {prefix}invoice WRITE, {prefix}settings READ' . ', {prefix}company READ' ); $res = mysqli_param_query( 'SELECT invoice_no, ref_number, base_id, company_id, invoice_date,' . "interval_type FROM $table WHERE id=?", [$primaryKey] ); $data = mysqli_fetch_assoc($res); $needInvNo = getSetting('invoice_add_number'); $needRefNo = getSetting('invoice_add_reference_number'); if (($needInvNo && empty($data['invoice_no'])) || ($needRefNo && empty($data['ref_number'])) ) { $defaults = getInvoiceDefaults( $primaryKey, $data['base_id'], $data['company_id'], dateConvDBDate2Date($data['invoice_date']), $data['interval_type'], $data['invoice_no'] ); $sql = "UPDATE {prefix}invoice SET"; $updateStrings = []; $params = []; if ($needInvNo && empty($data['invoice_no'])) { $updateStrings[] = 'invoice_no=?'; $params[] = $defaults['invoice_no']; } if ($needRefNo && empty($data['ref_number'])) { $updateStrings[] = 'ref_number=?'; $params[] = $defaults['ref_no']; } $sql .= ' ' . implode(', ', $updateStrings) . ' WHERE id=?'; $params[] = $primaryKey; mysqli_param_query($sql, $params); } mysqli_query_check('UNLOCK TABLES'); } return true; } // Fetch a record. Values in $values, may modify $formElements. // Returns TRUE on success, 'deleted' for deleted records and 'notfound' if record is not found. function fetchRecord($table, $primaryKey, &$formElements, &$values) { $result = TRUE; $strQuery = "SELECT * FROM $table WHERE id=?"; $intRes = mysqli_param_query($strQuery, [ $primaryKey ]); $row = mysqli_fetch_assoc($intRes); if (!$row) return 'notfound'; if ($row['deleted']) $result = 'deleted'; foreach ($formElements as $elem) { $type = $elem['type']; $name = $elem['name']; if (!$type || $type == 'LABEL' || $type == 'FILLER' || $type == 'DROPDOWNMENU' ) { continue; } switch ($type) { case 'IFORM' : case 'RESULT' : $values[$name] = $primaryKey; break; case 'BUTTON' : case 'JSBUTTON' : case 'IMAGE' : if (strstr($elem['listquery'], '=_ID_')) { $values[$name] = $primaryKey; } else { $tmpListQuery = $elem['listquery']; $strReplName = substr($tmpListQuery, strpos($tmpListQuery, '_')); $strReplName = strtolower( substr($strReplName, 1, strrpos($strReplName, '_') - 1)); $values[$name] = isset($values[$strReplName]) ? $values[$strReplName] : ''; $elem['listquery'] = str_replace(strtoupper($strReplName), 'ID', $elem['listquery']); } break; case 'INTDATE' : $values[$name] = dateConvDBDate2Date($row[$name]); break; case 'INT' : if (isset($elem['decimals'])) { $values[$name] = miscRound2Decim($row[$name], $elem['decimals']); } else { $values[$name] = $row[$name]; } break; default : $values[$name] = $row[$name]; } } return $result; } function getFormElements($form) { $strForm = $form; require 'form_switch.php'; return $astrFormElements; } function getFormParentKey($form) { $strForm = $form; require 'form_switch.php'; return $strParentKey; } function getFormJSONType($form) { $strForm = $form; require 'form_switch.php'; return $strJSONType; } function getFormClearRowValuesAfterAdd($form) { $strForm = $form; require 'form_switch.php'; return $clearRowValuesAfterAdd; } function getFormOnAfterRowAdded($form) { $strForm = $form; require 'form_switch.php'; return $onAfterRowAdded; }