0 ) $str .= "; " . implode(", ", $device_names); } $str .= ")"; return $str; } /** * Search for system components * * Input: * - i18n * - equipment_type Use equipment type (single or array) to search a * system component * - filter Component name or description to filter on * * Returns: * - Matching release items */ function db_search_system_components($i18n = NULL, $equipment_type = NULL, $type = NULL, $filter = NULL) { $query = "SELECT * FROM syscomp"; $sep = " WHERE "; if( is_numeric($equipment_type) ) { $query .= $sep . " id IN (SELECT syscomp FROM device_syscomp WHERE device=" . $equipment_type . ")"; $sep = " AND "; } else if( is_array($equipment_type) && !empty($equipment_type) ) { $query .= $sep . " id IN (SELECT syscomp FROM device_syscomp WHERE device IN (" . implode(",", $equipment_type) . "))"; $sep = " AND "; } if( $type ) { $query .= $sep . " syscomp.type='" . $type . "'"; // $sep = " AND "; } $system_components = db_fetch_data($query); // filter result set by name? also, retrieve the names and insert them into the array if( $i18n ) { $sort_by_name = array(); foreach( $system_components as $key => $system_component ) { $name = db_fetch_system_component_name($system_component['id'], $i18n); if( $filter && (!$name || stripos($name, $filter) === FALSE) ) { // not found unset($system_components[$key]); } else { // found: save this item's name $system_components[$key]['naam'] = $name; $sort_by_name[$key] = $name; } } // sort by name // 'array_multisort()' doesn't seem to work properly asort($sort_by_name, SORT_LOCALE_STRING | SORT_FLAG_CASE); $sorted = array(); foreach( $sort_by_name as $key => $value ) { $sorted[$key] = $system_components[$key]; } return $sorted; } else { return $system_components; } } /** * Fetch a system component by identifier * * Input: * - database identifier * - translation for the component's name * * Returns: * - system component (array, including the translation for 'naam' in all languages) */ function db_fetch_system_component($dbid, $i18n = NULL) { $query = "SELECT * FROM syscomp WHERE id=" . $dbid; $syscomp = db_fetch_data($query); if( $syscomp ) { $syscomp = $syscomp[0]; // get the component's name(s) if( $i18n ) { // get name in the preferred language, with fall-back $syscomp['naam'] = i18n_translate($dbid, 'syscomp.naam', $i18n); } else { $syscomp['naam'] = array(); $query = "SELECT tekst,i18n FROM vertaling WHERE id=" . $dbid . " AND field='syscomp.naam'"; $descriptions = db_fetch_data($query); if( $descriptions ) foreach( $descriptions as $description ) { $syscomp['naam'][$description['i18n']] = $description['tekst']; } } // get links to the device types $types = db_fetch_data("SELECT device AS id FROM device_syscomp WHERE syscomp=" . $dbid); $syscomp['device'] = array(); foreach( $types as $type ) $syscomp['device'][] = $type['id']; return $syscomp; } else return FALSE; } /** * Store system component * * Inputs: * - syscomp Array with system component data, as would have bee * returned by 'db_fetch_system_component()' * * Returns: * - Database identifier on success (> 0) or FALSE on error */ function db_store_system_component($syscomp) { // Start transaction db_start_transaction(); // Insert the syscomp information $query = "INSERT INTO syscomp (`versie_item`,`type`) VALUES ("; if( $syscomp['versie_item'] ) $query .= "'" . $syscomp['versie_item'] . "',"; else $query .= "NULL,"; $query .= "'" . $syscomp['type'] . "'"; $query .= ")"; if( !db_store_data($query) ) return FALSE; $syscomp['id'] = db_fetch_last_id(); // Store translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($syscomp['naam']) ) foreach( $syscomp['naam'] as $i18n => $naam ) { $query .= $sep . "('" . $i18n . "','syscomp.naam'," . $syscomp['id'] . ",'" . specialchars($naam) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','syscomp.naam'," . $syscomp['id'] . ",'" . specialchars($syscomp['naam']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $syscomp['id']; } /** * Update system component * * Inputs: * - syscomp Array with system component data, as would have bee * returned by 'db_fetch_system_component()' * * Returns: * - Database identifier on success (> 0) or FALSE on error */ function db_update_system_component($syscomp) { // Start transaction db_start_transaction(); // Update the syscomp information $query = "UPDATE syscomp SET"; if( $syscomp['versie_item'] ) $query .= " `versie_item`='" . $syscomp['versie_item'] . "',"; else $query .= " `versie_item`=NULL,"; $query .= " `type`='" . $syscomp['type'] . "'"; $query .= " WHERE id=" . $syscomp['id']; if( !db_store_data($query) ) return FALSE; // Delete old transltations $query = "DELETE FROM `vertaling` WHERE `id`=" . $syscomp['id'] . " AND `field` LIKE 'syscomp.%'"; db_store_data($query); // Store translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($syscomp['naam']) ) foreach( $syscomp['naam'] as $i18n => $naam ) { $query .= $sep . "('" . $i18n . "','syscomp.naam'," . $syscomp['id'] . ",'" . specialchars($naam) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','syscomp.naam'," . $syscomp['id'] . ",'" . specialchars($syscomp['naam']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $syscomp['id']; } /** * Delete system component * * Inputs: * - syscomp id Database identifier for the system component to delete * * Returns: * - Success (boolean) */ function db_delete_system_component($syscomp_id) { // Start transaction db_start_transaction(); // Delete device $query = "DELETE FROM syscomp WHERE id=" . $syscomp_id; db_store_data($query); // Delete link with device type $query = "DELETE FROM device_syscomp WHERE syscomp=" . $syscomp_id; db_store_data($query); // Delete link with versions $query = "DELETE FROM changelog_versie_syscomp WHERE syscomp=" . $syscomp_id; db_store_data($query); // Delete link with the descriptions $query = "DELETE FROM `vertaling` WHERE `id`=" . $syscomp_id . " AND `field` LIKE 'syscomp.%'"; db_store_data($query); // Delete documentation $query = "SELECT id FROM syscomp_documenten WHERE syscomp=" . $syscomp_id . " FOR UPDATE"; $docs = db_fetch_data($query); if( $docs ) foreach( $docs as $doc ) { db_delete_file($doc['id'], "syscomp_documenten"); } // Commit transaction return db_commit_transaction(); } /** * Link system component with an equipment type * * Inputs: * - syscomp_id Database identifier for the system component * - equipment_id Database identifier for the equipement type * - replace Replace current links when TRUE, add to the * current links when FALSE (will generate "duplicate * key" errors for those links that are already in * place and this is intentional) * * Returns: * Boolean (success or failure) */ function db_link_system_component($syscomp_id, $equipment_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($syscomp_id) ) { trigger_error("Numeric system component id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_syscomp WHERE syscomp=" . $syscomp_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_syscomp (device,syscomp) VALUES "; if( is_array($equipment_id) && count($equipment_id) > 0 ) { foreach( $equipment_id as $device ) { $query .= $sep . "(" . $device . "," . $syscomp_id . ")"; $sep = ","; } } else if( is_numeric($equipment_id) ) { $query = $sep . "(" . $equipment_id . "," . $syscomp_id . ")"; } else if( $equipment_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Link system components when an equipment type * Complementary to the function above * * - equipment_id Equipment type to link the system components to * - syscomp_id System components to link (single or array) * - replace Replace or augment current list * * Returns: * Boolean (success or error) */ function db_link_system_components($equipment_id, $syscomp_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($equipment_id) ) { trigger_error("Numeric equipment id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_syscomp WHERE device=" . $equipment_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_syscomp (device,syscomp) VALUES "; if( is_array($syscomp_id) && count($syscomp_id) > 0 ) { foreach( $syscomp_id as $syscomp ) { $query .= $sep . "(" . $equipment_id . "," . $syscomp . ")"; $sep = ","; } } else if( is_numeric($syscomp_id) ) { $query = $sep . "(" . $equipment_id . "," . $syscomp_id . ")"; } else if( $syscomp_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /************************************************************************/ /* */ /* Versions */ /* */ /************************************************************************/ /** * Search for versions * * Input: * - i18n (currently not used) * - syscomp_id Identifier(s) for the system component * - equipment_id Identifier(s) for the equipment type * - release type * - version_number Version number to filter on * * Returns: * - Matching version items */ function db_search_system_versions($i18n = NULL, $syscomp_id = NULL, $equipment_id = NULL, $release_type = NULL, $filter = NULL) { $query = "SELECT *"; // search for, but _don't_ filter by equipment type if( is_array($equipment_id) && count($equipment_id) > 0 ) { $query .= ",IF(id IN (SELECT versie FROM device_changelog_versie WHERE device IN (" . implode(",", $equipment_id) . ")),1,0) AS so_enable"; } else if( is_numeric($equipment_id) ) { $query .= ",IF(id IN (SELECT versie FROM device_changelog_versie WHERE device=" . $equipment_id . "),1,0) AS so_enable"; } else { // otherwise: always enabled $query .= ",1 as so_enable"; } $query .= " FROM changelog_versie"; $sep = " WHERE "; // filter by system component if( is_array($syscomp_id) ) { if( !$syscomp_id ) { // empty array, won't match anything so return empty array here return array(); } $query .= $sep . "id IN (SELECT versie FROM changelog_versie_syscomp WHERE syscomp IN (" . implode(",", $syscomp_id) . "))"; $sep = " AND "; } else if( is_numeric($syscomp_id) ) { $query .= $sep . "id IN (SELECT versie FROM changelog_versie_syscomp WHERE syscomp=" . $syscomp_id . ")"; $sep = " AND "; } // filter by release type if( $release_type ) { if( $release_type == "*" ) { // explicit search for "not set" $query .= $sep . "soort_release IS NULL"; } else { $query .= $sep . "soort_release='" . $release_type . "'"; } $sep = " AND "; } // filter on version number, date or description if( $filter ) { $query .= $sep . "(versienummer LIKE '%" . specialchars($filter) . "%'"; $query .= " OR datum LIKE '%" . specialchars($filter) . "%'"; $query .= " OR omschrijving LIKE '%" . specialchars($filter) . "%')"; $sep = " AND "; } $query .= " ORDER BY versienummer"; $versions = db_fetch_data_array('id', $query); // get links to the device types if( $versions && ($types = db_fetch_data("SELECT device,versie FROM device_changelog_versie WHERE versie IN (" . implode(",", array_keys($versions)) . ")")) ) { foreach( $versions as $id => $version ) $versions[$id]['device'] = array(); foreach( $types as $type ) $versions[$type['versie']]['device'][] = $type['device']; } if( $i18n ) { // sort by name $sort_by_name = array(); foreach( $versions as $key => $version ) { $sort_by_name[$key] = db_printf_system_version($version, FALSE); } // 'array_multisort()' doesn't seem to work properly asort($sort_by_name, SORT_LOCALE_STRING | SORT_FLAG_CASE); $sorted = array(); foreach( $sort_by_name as $key => $value ) { $sorted[$key] = $versions[$key]; } return $sorted; } else { return $versions; } } /** * Fetch a version * * Inputs: * - version_id Database identifier for the version _or_ subquery to fetch the * database identifier * * Returns: * - Version item (array), including supported syscomps */ function db_fetch_system_version($version_id) { if( !is_numeric($version_id) ) { // fetch with a subquery $version_id = "(" . $version_id . ")"; } $query = "SELECT * FROM changelog_versie WHERE id=" . $version_id; $version = db_fetch_data($query); if( !$version ) { return FALSE; } else { // only one result expected $version = $version[0]; // currently, only one system component expected $version['syscomp'] = db_fetch_item("SELECT syscomp FROM changelog_versie_syscomp WHERE versie=" . $version['id']); // get links to the device types $types = db_fetch_data("SELECT device AS id FROM device_changelog_versie WHERE versie=" . $version['id']); $version['device'] = array(); if( $types ) foreach( $types as $type ) $version['device'][] = $type['id']; return $version; } } /** * Fetch existing versions (all, for a type of equipment or a device) from * the table 'zkl' * DEPRECATED - no longer wanted * * Inputs: * - syscomp_id System component (database identifier) * - equipment_id Device type (database identifier; optional) * * Returns: * - Array with version numbers */ function db_fetch_system_versions($syscomp, $equipment_id = NULL) { if( ($version_item = db_fetch_item("SELECT versie_item FROM syscomp WHERE id=" . $syscomp)) === FALSE || count($version_item) == 0 ) return FALSE; $query = "SELECT " . $version_item . " AS version,device"; $query .= " FROM zkl"; $sep = " WHERE "; if( $equipment_id ) { $query .= $sep . "device=" . $equipment_id; $sep = " AND "; } else { $query .= $sep . "device IN (SELECT device FROM device_syscomp WHERE syscomp=" . $syscomp . ")"; $sep = " AND "; } $query .= " GROUP BY " . $version_item . ",device"; $db_versions = db_fetch_data($query); $versions = array(); if( is_array($db_versions) ) foreach( $db_versions as $db_version ) { $version_str = db_format_system_version($version_item, $db_version['version']); if( $version_str && !in_array($version_str, $versions) ) $versions[] = array('version' => $version_str, 'device' => $db_version['device']); arsort($versions); } return $versions; } /** * Re-format a version string * * Inputs: * - version_item Version item (database field in the table 'zkl') * - version_str Unformatted string * * Returns: * - Formatted version string */ function db_format_system_version($version_item, $version_str) { switch( $version_item ) { case 'mcu_versie': case 'sw3000_dversie': case 'sw3000_mversie': case 'wcpu_versie': if( preg_match("/^[0-9]+\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?-[0-9]{8}(-.+)?$/", $version_str) ) { $version_info = zkl_get_fw_version($version_str); return sprintf("%u.%02u-%08X", $version_info['major'], $version_info['minor'], $version_info['datecode']); } else return FALSE; case 'wavecom_versie': if( preg_match("/^(R[0-9]+\.[0-9]+|^[^.]+)/", $version_str, $version_matches) ) { return $version_matches[1]; } else return FALSE; case 'mcu_revisie': case 'wavecom_revisie': case 'ualfat_versie': case 'pcb_versie': case 'pcb_revisie': case 'mech_versie': case 'sw3000_versie': case 'sw3000_drevisie': case 'sw3000_mrevisie': return $version_str; default: return FALSE; } } /** * Compare (formatted) versions * * Inputs: * - v1 and v2 Version strings to compare * - version_item Determines how to compare (field in table 'syscomp' and 'zkl') * * Returns: * - < 0 when v1 < v2 * - 0 when v1 == v2 * - > 0 when v1 > v2 * - FALSE on error or not supported */ function db_compare_system_version($v1, $v2, $version_item) { switch( $version_item ) { case 'mcu_versie': case 'sw3000_dversie': case 'sw3000_mversie': case 'wcpu_versie': $v1_info = zkl_get_fw_version($v1); $v2_info = zkl_get_fw_version($v2); $compare = "array"; break; case 'wavecom_versie': if( preg_match("/^R([0-9]+)\.([0-9]+)/", $v1, $v1_info) ) { array_splice($v1_info, 1); } else if( preg_match("/^R?([0-9])([0-9]{1,2})([_a-z])/", $v1, $v1_info) ) { array_splice($v1_info, 1); // version encoding for older Wavecom firmware uses underscore to // indicate "no revision"; we want it to be less than e.g. "a" if( $v1_info[2] == "_" ) $v1_info[2] = ""; } else return FALSE; if( preg_match("/^R([0-9]+)\.([0-9]+)/", $v2, $v2_info) ) { array_splice($v2_info, 1); } else if( preg_match("/^R?([0-9])([0-9]{1,2})([_a-z])/", $v2, $v2_info) ) { array_splice($v2_info, 1); if( $v2_info[2] == "_" ) $v2_info[2] = ""; } else return FALSE; $compare = "array"; break; case 'mcu_revisie': // not supported return FALSE; case 'wavecom_revisie': if( preg_match("/^([0-9]+)\.([0-9]+))/", $v1, $v1_info) && preg_match("/^([0-9]+)\.([0-9]+))/", $v2, $v2_info) ) { array_splice($v1_info, 1); array_splice($v2_info, 1); $compare = "array"; break; } else return FALSE; case 'ualfat_versie': if( (substr($v1, 0, 7) == "uALFAT ") && (substr($v2, 0, 7) == "uALFAT ") ) { $v1 = substr($v1, 7); $v2 = substr($v2, 7); $compare = "numeric"; break; } else return FALSE; case 'pcb_versie': case 'pcb_revisie': case 'mech_versie': case 'sw3000_versie': $compare = "numeric"; break; default: return FALSE; } if( $compare == "array" ) { // the components should be in the right order, i.e. major number // first, then minor, etc. foreach( $v1_info as $key => $v1_comp ) { if( $v1_comp != $v2_info[$key] ) { if( is_numeric($v1_comp) ) return $v1_comp - $v2_info[$key]; else return strcmp($v1_comp, $v2_info[$key]); } } // versions match return 0; } else if( $compare = "numeric" ) { return $v1 - $v2; } else return FALSE; } /** * Format a version item for display * * Input: * - version Version info (array) _or_ version item * - full_context Show full context (system components) * * Returns: * - string */ function db_printf_system_version($version, $full_context = TRUE) { global $_PAGE_INFO; $str = $version['omschrijving']; $sep = " ("; if( $full_context ) { if( !isset($version['syscomp']) ) { $version['syscomp'] = db_fetch_item("SELECT syscomp FROM changelog_versie_syscomp WHERE versie=" . $version['id']); } if( $version['syscomp'] ) { $syscomp = db_fetch_system_component($version['syscomp'], $_SESSION[$_PAGE_INFO['id']]['i18n']); $str .= $sep . $syscomp['naam']; $sep = ", "; } } if( $version['versienummer'] ) { $str .= $sep . $version['versienummer']; $sep = ", "; } if( $version['datum'] ) { $str .= $sep . $version['datum']; $sep = ", "; } if( $sep != " (" ) $str .= ")"; return $str; } /** * Store version * * Inputs: * - version Array with version item data, as would have bee * returned by 'db_fetch_version_item()' * * Returns: * - Database identifier on success (> 0) or FALSE on error * - Database identifier is inserted into the input array 'version' */ function db_store_system_version($version) { // start transaction db_start_transaction(); // Insert the version information $query = "INSERT INTO changelog_versie (versienummer,datum,soort_release,omschrijving) VALUES ("; if( $version['versienummer'] ) $query .= "'" . specialchars($version['versienummer']) . "',"; else $query .= "NULL,"; if( $version['datum'] ) $query .= "'" . $version['datum'] . "',"; else $query .= "NULL,"; if( $version['soort_release'] ) $query .= "'" . $version['soort_release'] . "',"; else $query .= "NULL,"; $query .= "'" . specialchars($version['omschrijving']) . "')"; if( !db_store_data($query) ) return FALSE; $version['id'] = db_fetch_last_id(); $query = ""; $sep = "INSERT INTO changelog_versie_syscomp (syscomp,versie) VALUES "; if( is_array($version['syscomp']) ) foreach( $version['syscomp'] AS $syscomp ) { $query .= $sep . "(" . $syscomp . "," . $version['id'] . ")"; $sep = ","; } else if( is_numeric($version['syscomp']) ) { $query .= $sep . "(" . $version['syscomp'] . "," . $version['id'] . ")"; } if( $query ) db_store_data($query); // commit transaction if( !db_commit_transaction() ) return FALSE; return $version['id']; } /** * Update version * * Inputs: * - version item Array with version item data, as would have bee * returned by 'db_fetch_version_item()' * * Returns: * - Database identifier on success (> 0) or FALSE on error */ function db_update_system_version($version) { // Start transaction db_start_transaction(); // Update the version information $query = "UPDATE changelog_versie SET"; $query .= " versienummer=" . ($version['versienummer'] ? ("'" . specialchars($version['versienummer']) . "'") : "NULL") . ","; $query .= " datum=" . ($version['datum'] ? ("'" . $version['datum'] . "'") : "NULL") . ","; $query .= " soort_release=" . ($version['soort_release'] ? ("'" . $version['soort_release'] . "'") : "NULL") . ","; $query .= " omschrijving='" . specialchars($version['omschrijving']) . "'"; $query .= " WHERE id=" . $version['id']; if( !db_store_data($query) ) return FALSE; // Update the system components for which this version is valid $query = "DELETE FROM changelog_versie_syscomp WHERE versie=" . $version['id']; db_store_data($query); $query = ""; $sep = "INSERT INTO changelog_versie_syscomp (syscomp,versie) VALUES "; if( is_array($version['syscomp']) ) foreach( $version['syscomp'] AS $syscomp ) { $query .= $sep . "(" . $syscomp . "," . $version['id'] . ")"; $sep = ","; } else if( is_numeric($version['syscomp']) ) { $query .= $sep . "(" . $version['syscomp'] . "," . $version['id'] . ")"; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $version['id']; } /** * Delete version * * Inputs: * - version id Database identifier for the version to delete * * Returns: * - Success (boolean) */ function db_delete_system_version($version_id) { // Start transaction db_start_transaction(); // Delete device $query = "DELETE FROM changelog_versie WHERE id=" . $version_id; db_store_data($query); // Delete links with the system component $query = "DELETE FROM changelog_versie_syscomp WHERE versie=" . $version_id; db_store_data($query); // Delete links to the device type $query = "DELETE FROM device_changelog_versie WHERE versie=" . $version_id; db_store_data($query); // Delete documentation $query = "SELECT id FROM changelog_versie_documenten WHERE versie=" . $version_id . " FOR UPDATE"; $docs = db_fetch_data($query); if( $docs ) foreach( $docs as $doc ) { db_delete_file($doc['id'], "changelog_versie_documenten"); } // Commit transaction return db_commit_transaction(); } /** * Link version with an equipment type (version is applicable for the equipment type) * * Inputs: * - versie_id Database identifier for the system component * - equipment_id Database identifier for the equipement type * - replace Replace current links when TRUE, add to the * current links when FALSE (will generate "duplicate * key" errors for those links that are already in * place and this is intentional) * * Returns: * Boolean (success or failure) */ function db_link_system_version($version_id, $equipment_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($version_id) ) { trigger_error("Numeric version id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_changelog_versie WHERE versie=" . $version_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_changelog_versie (device,versie) VALUES "; if( is_array($equipment_id) && count($equipment_id) > 0 ) { foreach( $equipment_id as $device ) { $query .= $sep . "(" . $device . "," . $version_id . ")"; $sep = ","; } } else if( is_numeric($equipment_id) ) { $query = $sep . "(" . $equipment_id . "," . $version_id . ")"; } else if( $equipment_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Link system components when an equipment type (version is applicable for the equipment type) * Complementary to the function above * * - equipment_id Equipment type to link the system components to * - versie_id Version to link (single or array) * - replace Replace or augment current list * * Returns: * Boolean (success or error) */ function db_link_system_versions($equipment_id, $version_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($equipment_id) ) { trigger_error("Numeric equipment id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_changelog_versie WHERE device=" . $equipment_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_changelog_versie (device,versie) VALUES "; if( is_array($version_id) && count($version_id) > 0 ) { foreach( $version_id as $version ) { $query .= $sep . "(" . $equipment_id . "," . $version . ")"; $sep = ","; } } else if( is_numeric($version_id) ) { $query = $sep . "(" . $equipment_id . "," . $version_id . ")"; } else if( $version_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Fetch workorders that use a version * * Inputs: * - versie_id Database identifier for the system component * * Returns: * An array with workorder identifiers, or FALSE on error */ function db_fetch_linked_versions($version_id) { return db_fetch_data("SELECT * FROM zkl_werkorder_werkopdracht WHERE link_table='changelog_versie' AND link_id=" . $version_id); } /************************************************************************/ /* */ /* Changes (change log) */ /* */ /************************************************************************/ /** * Search for version changes * * Input: * - i18n * - version_id Identifier(s) from the version * - equipment_id Identifier(s) for the equipment type * - syscomp_id Identifier(s) for the system component * - filter Filter for * * Returns: * - Matching version items */ function db_search_version_changelog($i18n = FALSE, $version_id = NULL, $equipment_id = NULL, $syscomp_id = NULL, $filter = NULL) { $query = "SELECT *"; // search for, but _don't_ filter by equipment type if( is_array($equipment_id) && count($equipment_id) > 0 ) { $query .= ",IF(id IN (SELECT versie_change FROM device_changelog_versie_change WHERE device IN (" . implode(",", $equipment_id) . ")),1,0) AS so_enable"; } else if( is_numeric($equipment_id) ) { $query .= ",IF(id IN (SELECT versie_change FROM device_changelog_versie_change WHERE device=" . $equipment_id . "),1,0) AS so_enable"; } else { // otherwise: always enabled $query .= ",1 as so_enable"; } $query .= " FROM changelog_versie_change"; $sep = " WHERE "; // filter by version or system component if( is_array($version_id) && count($version_id) > 0 ) { $query .= $sep . "versie IN (" . implode(",", $version_id) . ")"; $sep = " AND "; } else if( is_numeric($version_id) ) { $query .= $sep . "versie=" . $version_id; $sep = " AND "; } else if( is_array($syscomp_id) && count($syscomp_id) > 0 ) { $query .= $sep . "versie IN (SELECT versie FROM changelog_versie_syscomp WHERE syscomp IN (" . implode(",", $syscomp_id) . "))"; $sep = " AND "; } else if( is_numeric($syscomp_id) ) { $query .= $sep . "versie IN (SELECT versie FROM changelog_versie_syscomp WHERE syscomp=" . $syscomp_id . ")"; $sep = " AND "; } $changes = db_fetch_data($query); // filter result set by name? also, retrieve the names and insert them into the array if( $i18n && $changes ) { $sort_by_name = array(); foreach( $changes as $key => $change ) { $name = i18n_translate($change['id'], 'changelog_versie_change.omschrijving', $i18n); if( $filter && (!$name || stripos($name, $filter) === FALSE) ) { // not found unset($changes[$key]); } else { // found: save this item's description $changes[$key]['omschrijving'] = $name; $sort_by_name[$key] = $name; } } // sort by name // 'array_multisort()' doesn't seem to work properly asort($sort_by_name, SORT_LOCALE_STRING | SORT_FLAG_CASE); $sorted = array(); foreach( $sort_by_name as $key => $value ) { $sorted[$key] = $changes[$key]; } return $sorted; } else { return $changes; } } /** * Fetch a change log entry * * Inputs: * - changelog_id Database identifier for the change * - i18n Requested language or all languages when not set * * Returns: * - Change log entries on success or FALSE on error */ function db_fetch_version_change($changelog_id, $i18n = NULL) { $query = "SELECT * FROM changelog_versie_change WHERE id=" . $changelog_id; $change = db_fetch_data($query); if( !$change ) return FALSE; else $change = $change[0]; if( $i18n ) { // get name etc. in the preferred language, with fall-back $change['omschrijving'] = i18n_translate($changelog_id, 'changelog_versie_change.omschrijving', $i18n); $change['uitleg'] = i18n_translate($changelog_id, 'changelog_versie_change.uitleg', $i18n); } else { $query = "SELECT i18n,REPLACE(field,'changelog_versie_change.','') AS item,tekst FROM vertaling"; $query .= " WHERE"; $query .= " id=" . $changelog_id . " AND "; $query .= " field LIKE 'changelog_versie_change.%'"; $vertalingen = db_fetch_data($query); if( $vertalingen ) foreach( $vertalingen as $vertaling ) { // all languages $change[$vertaling['item']][$vertaling['i18n']] = $vertaling['tekst']; } } // get links to the device types $types = db_fetch_data("SELECT device AS id FROM device_changelog_versie_change WHERE versie_change=" . $change['id']); $change['device'] = array(); if( $types ) foreach( $types as $type ) $change['device'][] = $type['id']; return $change; } /** * Fetch change log entries for a version item * * Inputs: * - version Database identifier for this version item * - i18n Requested language or all languages when not set * * Returns: * - Change log entries on success (indexed by database identifier) or FALSE on error */ function db_fetch_version_changelog($version, $i18n = FALSE) { $query = "SELECT * FROM changelog_versie_change WHERE versie=" . $version . " ORDER BY volgorde"; $data = db_fetch_data($query); if( !$data ) return FALSE; // re-order the array $changes = array(); foreach( $data as $change ) { $id = $change['id']; $changes[$id] = $change; $changes[$id]['device'] = array(); if( $i18n ) { // get name etc. in the preferred language, with fall-back $changes[$id]['omschrijving'] = i18n_translate($change['id'], 'changelog_versie_change.omschrijving', $i18n); $changes[$id]['uitleg'] = i18n_translate($change['id'], 'changelog_versie_change.uitleg', $i18n); } else { $query = "SELECT i18n,REPLACE(field,'changelog_versie_change.','') AS item,tekst FROM vertaling"; $query .= " WHERE"; $query .= " id=" . $change['id'] . " AND "; $query .= " field LIKE 'changelog_versie_change.%'"; $vertalingen = db_fetch_data($query); if( $vertalingen ) foreach( $vertalingen as $vertaling ) { // all languages $changes[$id][$vertaling['item']][$vertaling['i18n']] = $vertaling['tekst']; } } } // get links to the device types $types = db_fetch_data("SELECT device,versie_change FROM device_changelog_versie_change WHERE versie_change IN (" . implode(",", array_keys($changes)) . ")"); if( $types ) { foreach( $types as $type ) $changes[$type['versie_change']]['device'][] = $type['device']; } return $changes; } /** * Format a change log entry for display * * Input: * - change Change log entry (array or database identifier) * - full_context Show full context (not defined for change log entries) * * Returns: * - string */ function db_printf_version_changelog($change, $full_context = TRUE) { global $_PAGE_INFO; if( $change['omschrijving'] ) { if( is_array($change['omschrijving']) ) { // select an appropriate translation from all languages $str = i18n_translate($change['omschrijving'], 'changelog_versie_change.omschrijving', $_SESSION[$_PAGE_INFO['id']]['i18n']); } else { // item already has a name $str = $change['omschrijving']; } } else { // fetch translation from the database if( is_array($change) ) $id = $change['id']; else $id = $change; // assume to be a database identifier $str = i18n_translate($id, 'changelog_versie_change.omschrijving', $_SESSION[$_PAGE_INFO['id']]['i18n']); } return $str; } /** * Store a change log entry * * Inputs: * - version System version for which this is a change * - change Entry for the change log, including translations in all languages * * Returns * - Database identifier on success, or FALSE on error * - Database identifier is inserted into the input array 'change' */ function db_store_version_changelog($version, $change) { // Get database identifier for the version if( is_array($version) ) $version_id = $version['id']; else if( is_numeric($version) ) $version_id = $version; else return FALSE; // Insert the change $query = "INSERT INTO changelog_versie_change (`versie`,`volgorde`,`service`) VALUES ("; $query .= $version_id . ","; $query .= $change['volgorde'] . ","; $query .= "'" . ($change['service'] ? "yes" : "no") . "')"; if( !db_store_data($query) ) return FALSE; $change['id'] = db_fetch_last_id(); // Store translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($change['omschrijving']) ) foreach( $change['omschrijving'] as $i18n => $omschrijving ) { $query .= $sep . "('" . $i18n . "','changelog_versie_change.omschrijving'," . $change['id'] . ",'" . specialchars($omschrijving) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','changelog_versie_change.omschrijving'," . $change['id'] . ",'" . specialchars($change['omschrijving']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Store translations for the explanation/procedure $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($change['uitleg']) ) foreach( $change['uitleg'] as $i18n => $uitleg ) { $query .= $sep . "('" . $i18n . "','changelog_versie_change.uitleg'," . $change['id'] . ",'" . specialchars($uitleg) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','changelog_versie_change.uitleg'," . $change['id'] . ",'" . specialchars($change['uitleg']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; return $change['id']; } /** * Update a change log entry * * Inputs: * - change Entry for the change log * Translations are updated when the array (!) 'omschrijving' is * present in the input array. * * Returns * - Database identifier on success, or FALSE on error */ function db_update_version_changelog($change) { // Start transaction db_start_transaction(); // Update the change log item $query = "UPDATE changelog_versie_change SET"; $query .= " `volgorde`=" . $change['volgorde'] . ","; $query .= " `service`='" . ($change['service'] ? "yes" : "no") . "'"; // NB: 'versie' cannot be changed! if( !db_store_data($query) ) return FALSE; // Delete existing translations $query = "DELETE FROM vertaling WHERE `id`=" . $change['id'] . " AND `field` LIKE 'changelog_versie_change.%'"; db_store_data($query); // Store the new translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($change['omschrijving']) ) foreach( $change['omschrijving'] as $i18n => $omschrijving ) { $query .= $sep . "('" . $i18n . "','changelog_versie_change.omschrijving'," . $change['id'] . ",'" . specialchars($omschrijving) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','changelog_versie_change.omschrijving'," . $change['id'] . ",'" . specialchars($change['omschrijving']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Store the new translations for the explanation/procedure $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($change['uitleg']) ) foreach( $change['uitleg'] as $i18n => $uitleg ) { $query .= $sep . "('" . $i18n . "','changelog_versie_change.uitleg'," . $change['id'] . ",'" . specialchars($uitleg) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','changelog_versie_change.uitleg'," . $change['id'] . ",'" . specialchars($change['uitleg']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $change['id']; } /** * Delete a change log entry * * Inputs: * - change_id Change log entry identifier */ function db_delete_version_changelog($change_id) { // Start transaction db_start_transaction(); // Delete change $query = "DELETE FROM changelog_versie_change WHERE id=" . $change_id; db_store_data($query); // Delete links ("applicable for") with the equipment types $query = "DELETE FROM device_changelog_versie_change WHERE versie_change=" . $change_id; db_store_data($query); // Delete translations $query = "DELETE FROM vertaling WHERE `id`=" . $change_id . " AND `field` LIKE 'changelog_versie_change.%'"; db_store_data($query); // Delete documentation $query = "SELECT id FROM changelog_versie_change_documenten WHERE versie_change=" . $change_id . " FOR UPDATE"; $docs = db_fetch_data($query); if( $docs ) foreach( $docs as $doc ) { db_delete_file($doc['id'], "changelog_versie_change_documenten"); } // Commit transaction return db_commit_transaction(); } /** * Link a change log item with an equipment type (version is applicable for the equipment type) * * Inputs: * - change_id Database identifier for the change log item * - equipment_id Database identifier for the equipement type * - replace Replace current links when TRUE, add to the * current links when FALSE (will generate "duplicate * key" errors for those links that are already in * place and this is intentional) * * Returns: * Boolean (success or failure) */ function db_link_version_changelog($change_id, $equipment_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($change_id) ) { trigger_error("Numeric version id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_changelog_versie_change WHERE versie_change=" . $change_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_changelog_versie_change (device,versie_change) VALUES "; if( is_array($equipment_id) && count($equipment_id) > 0 ) { foreach( $equipment_id as $device ) { $query .= $sep . "(" . $device . "," . $change_id . ")"; $sep = ","; } } else if( is_numeric($equipment_id) ) { $query = $sep . "(" . $equipment_id . "," . $change_id . ")"; } else if( $equipment_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Link system components when an equipment type (version is applicable for the equipment type) * Complementary to the function above * * - equipment_id Equipment type to link the system components to * - change_id Change log item(s) to link (single or array) * - replace Replace or augment current list * * Returns: * Boolean (success or error) */ function db_link_version_changelogs($equipment_id, $change_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($equipment_id) ) { trigger_error("Numeric equipment id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM device_changelog_versie_change WHERE device=" . $equipment_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO device_changelog_versie_change (device,versie_change) VALUES "; if( is_array($change_id) && count($change_id) > 0 ) { foreach( $change_id as $change ) { $query .= $sep . "(" . $equipment_id . "," . $change . ")"; $sep = ","; } } else if( is_numeric($change_id) ) { $query = $sep . "(" . $equipment_id . "," . $change_id . ")"; } else if( $change_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Fetch workorders that use a change log item * * Inputs: * - change_id Change log item * * Returns: * An array with workorder identifiers, or FALSE on error */ function db_fetch_linked_version_changelogs($change_id) { return db_fetch_data("SELECT * FROM zkl_werkorder_werkopdracht WHERE link_table='changelog_versie_change' AND link_id=" . $change_id); } /************************************************************************/ /* */ /* Workorder items (templates) */ /* */ /************************************************************************/ /** * Search for workorder items * * Input: * - equipment_type Use equipment type (single or array) to search a * workorder item * - filter Name to filter on * * Returns: * - Matching release items */ function db_search_workorder_items($i18n, $equipment_type = NULL, $type = NULL, $filter = NULL) { $query = "SELECT * FROM werkopdracht"; $sep = " WHERE "; if( is_numeric($equipment_type) ) { $query .= $sep . " werkopdracht.id IN (SELECT werkopdracht FROM werkopdracht_device WHERE device=" . $equipment_type . ")"; $sep = " AND "; } else if( is_array($equipment_type) && !empty($equipment_type) ) { $query .= $sep . " werkopdracht.id IN (SELECT werkopdracht FROM werkopdracht_device WHERE device IN (" . implode(",", $equipment_type) . "))"; $sep = " AND "; } if( $type ) { $query .= $sep . " werkopdracht.type='" . $type . "'"; // $sep = " AND "; } $query .= " ORDER BY artikelnr"; $workorder_items = db_fetch_data($query); // filter result set by name? if( $workorder_items ) { foreach( $workorder_items as $key => $workorder_item ) { $name = db_fetch_workorder_item_name($workorder_item['id'], $i18n); if( ($filter && stripos($workorder_item['artikelnr'], $filter) === FALSE) && (!$name || ($filter && stripos($name, $filter) === FALSE)) ) { // not found unset($workorder_items[$key]); } else { // found: save this item's name $workorder_items[$key]['naam'] = $name; } } } return $workorder_items; } /** * Fetch a workorder item by identifier * * Input: * - database identifier * - translation for the component's name * * Returns: * - workorder item (array, including the translation for 'naam' in all languages) */ function db_fetch_workorder_item($dbid, $i18n = NULL) { $query = "SELECT * FROM werkopdracht WHERE id=" . $dbid; $woitem = db_fetch_data($query); if( $woitem ) { $woitem = $woitem[0]; // get the workorder's name(s) if( $i18n ) { // get name etc. in the preferred language, with fall-back $woitem['naam'] = i18n_translate($woitem['id'], 'werkopdracht.naam', $i18n); $woitem['uitleg'] = i18n_translate($woitem['id'], 'werkopdracht.uitleg', $i18n); } else { $query = "SELECT i18n,REPLACE(field,'werkopdracht.','') AS item,tekst FROM vertaling"; $query .= " WHERE id=" . $dbid; $query .= " AND field LIKE 'werkopdracht.%'"; $vertalingen = db_fetch_data($query); if( $vertalingen ) foreach( $vertalingen as $vertaling ) { // all translations $woitem[$vertaling['item']][$vertaling['i18n']] = $vertaling['tekst']; } } // get links to the device types $types = db_fetch_data("SELECT device FROM werkopdracht_device WHERE werkopdracht=" . $dbid); $woitem['device'] = array(); foreach( $types as $type ) $woitem['device'][] = $type['device']; // get item price $prices = db_fetch_data("SELECT bedrag,valuta FROM werkopdracht_kosten WHERE werkopdracht=" . $dbid); $woitem['kosten'] = array(); foreach( $prices as $price ) $woitem['kosten'][$price['valuta']] = $price['bedrag']; return $woitem; } else return FALSE; } /** * Fetch name or explanation for a workorder item * * Inputs: * - dbid Database identifier for the workorder item * - i18n Language * * Returns: * Name (string) or FALSE when not found */ function db_fetch_workorder_item_name($dbid, $i18n = NULL) { global $_PAGE_INFO; if( !$i18n ) $i18n = $_SESSION[$_PAGE_INFO['id']]['i18n']; return i18n_translate($dbid, 'werkopdracht.naam', $i18n); } function db_fetch_workorder_item_explanation($dbid, $i18n = NULL) { global $_PAGE_INFO; if( !$i18n ) $i18n = $_SESSION[$_PAGE_INFO['id']]['i18n']; return i18n_translate($dbid, 'werkopdracht.uitleg', $i18n); } function db_fetch_workorder_item_costs($dbid, $valuta) { global $_PAGE_INFO; $prices = db_fetch_data("SELECT bedrag,valuta FROM werkopdracht_kosten WHERE werkopdracht=" . $dbid); foreach( $prices as $price ) if( $price['valuta'] == $valuta ) return $price['bedrag']; return FALSE; } /** * Format a workorder item for display * * Input: * - woitem work order iteminfo (array) * - full_context Show full context (all device types) * * Returns: * - string */ function db_printf_workorder_item($woitem, $full_context = TRUE) { global $_PAGE_INFO; $str = $woitem['artikelnr'] . " - "; if( $woitem['naam'] ) { if( is_array($woitem['naam']) ) { // select an appropriate translation from all languages $str .= i18n_translate($woitem['naam'], 'werkopdracht.naam', $_SESSION[$_PAGE_INFO['id']]['i18n']); } else { // item already has a name $str .= $woitem['naam']; } } else { // fetch translation from the database $str .= i18n_translate($woitem['id'], 'werkopdracht.naam', $_SESSION[$_PAGE_INFO['id']]['i18n']); } $str .= " (" . _("woitem-descr:" . $woitem['type']); if( $full_context ) { $device_names = array(); if( $woitem['device'] ) { foreach( $woitem['device'] as $devicetype_id ) { $device_names[] = db_fetch_system_device_name($_SESSION[$_PAGE_INFO['id']]['i18n'], $devicetype_id); } } else { $devices = db_fetch_data("SELECT device FROM werkopdracht_device WHERE werkopdracht=" . $woitem['id']); if( is_array($devices) ) foreach( $devices as $device ) { $device_names[] = db_fetch_system_device_name($_SESSION[$_PAGE_INFO['id']]['i18n'], $device['device']); } } if( count($device_names) > 0 ) $str .= ", " . implode(", ", $device_names); } $str .= ")"; return $str; } /** * Store workorder item * * Inputs: * - woitem Array with workorder item data, as would have been * returned by 'db_fetch_workorder_item()' * * Returns: * - Database identifier on success (> 0) or FALSE on error */ function db_store_workorder_item($woitem) { // Start transaction db_start_transaction(); // Insert the werkopdracht information $query = "INSERT INTO werkopdracht (`artikelnr`,`service`,`fleetservice`,`type`,`soort_opdracht`) VALUES ("; $query .= "'" . specialchars($woitem['artikelnr']) . "',"; $query .= "'" . ($woitem['service'] ? "yes" : "no") . "',"; $query .= "'" . ($woitem['fleetservice'] ? "yes" : "no") . "',"; $query .= "'" . $woitem['type'] . "',"; $query .= "'" . $woitem['soort_opdracht'] . "')"; if( !db_store_data($query) ) return FALSE; $woitem['id'] = db_fetch_last_id(); // Store translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($woitem['naam']) ) foreach( $woitem['naam'] as $i18n => $naam ) { $query .= $sep . "('" . $i18n . "','werkopdracht.naam'," . $woitem['id'] . ",'" . specialchars($naam) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','werkopdracht.naam'," . $woitem['id'] . ",'" . specialchars($woitem['naam']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Store translations for the explanation and/or procedure $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($woitem['uitleg']) ) foreach( $woitem['uitleg'] as $i18n => $uitleg ) { $query .= $sep . "('" . $i18n . "','werkopdracht.uitleg'," . $woitem['id'] . ",'" . specialchars($uitleg) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','werkopdracht.uitleg'," . $woitem['id'] . ",'" . specialchars($woitem['uitleg']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Links to the equipment type $query = ""; $sep = "INSERT INTO werkopdracht_device (`werkopdracht`,`device`) VALUES "; foreach( $woitem['device'] as $device ) { $query .= $sep . "(" . $woitem['id'] . "," . $device . ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Item price $query = ""; $sep = "INSERT INTO werkopdracht_kosten (`werkopdracht`,`valuta`,`bedrag`) VALUES "; foreach( $woitem['kosten'] as $valuta => $bedrag ) { $query .= $sep . "(" . $woitem['id'] . ",'" . $valuta . "'," . $bedrag . ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $woitem['id']; } /** * Update workorder item * * Inputs: * - woitem Array with workorder item data, as would have been * returned by 'db_fetch_workorder_item()' * * Returns: * - Database identifier on success (> 0) or FALSE on error */ function db_update_workorder_item($woitem) { // Start transaction db_start_transaction(); // Update the werkopdracht information $query = "UPDATE werkopdracht SET"; $query .= " `artikelnr`='" . specialchars($woitem['artikelnr']) . "',"; $query .= " `service`='" . ($woitem['service'] ? "yes" : "no") . "',"; $query .= " `fleetservice`='" . ($woitem['fleetservice'] ? "yes" : "no") . "',"; $query .= " `type`='" . $woitem['type'] . "',"; $query .= " `soort_opdracht`='" . $woitem['soort_opdracht'] . "'"; $query .= " WHERE id=" . $woitem['id']; if( !db_store_data($query) ) return FALSE; // Delete old transltations $query = "DELETE FROM `vertaling` WHERE `id`=" . $woitem['id'] . " AND `field` LIKE 'werkopdracht.%'"; db_store_data($query); // Store translations for the description $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($woitem['naam']) ) foreach( $woitem['naam'] as $i18n => $naam ) { $query .= $sep . "('" . $i18n . "','werkopdracht.naam'," . $woitem['id'] . ",'" . specialchars($naam) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','werkopdracht.naam'," . $woitem['id'] . ",'" . specialchars($woitem['naam']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Store translations for the explanation and/or procedure $query = ""; $sep = "INSERT INTO vertaling (`i18n`,`field`,`id`,`tekst`) VALUES "; if( is_array($woitem['uitleg']) ) foreach( $woitem['uitleg'] as $i18n => $uitleg ) { $query .= $sep . "('" . $i18n . "','werkopdracht.uitleg'," . $woitem['id'] . ",'" . specialchars($uitleg) . "')"; $sep = ","; } else { global $_PAGE_INFO; $query .= $sep . "('" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "','werkopdracht.uitleg'," . $woitem['id'] . ",'" . specialchars($woitem['uitleg']) . "')"; $sep = ","; // not necessary, but hey! } if( $query && !db_store_data($query) ) return FALSE; // Replace links to the equipment type db_store_data("DELETE FROM werkopdracht_device WHERE werkopdracht=" . $woitem['id']); $query = ""; $sep = "INSERT INTO werkopdracht_device (`werkopdracht`,`device`) VALUES "; foreach( $woitem['device'] as $device ) { $query .= $sep . "(" . $woitem['id'] . "," . $device . ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Item price - all items should be present $query = ""; $sep = "REPLACE INTO werkopdracht_kosten (`werkopdracht`,`valuta`,`bedrag`) VALUES "; foreach( $woitem['kosten'] AS $valuta => $bedrag ) { $query .= $sep . "(" . $woitem['id'] . ",'" . $valuta . "'," . $bedrag . ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction if( !db_commit_transaction() ) return FALSE; return $woitem['id']; } /** * Delete workorder item * * Inputs: * - woitem_id Database identifier for the workorder item to delete * * Returns: * - Success (boolean) */ function db_delete_workorder_item($woitem_id) { // Start transaction db_start_transaction(); // Delete device $query = "DELETE FROM werkopdracht WHERE id=" . $woitem_id; db_store_data($query); // Delete link with the descriptions $query = "DELETE FROM `vertaling` WHERE `id`=" . $woitem_id . " AND `field` LIKE 'werkopdracht.%'"; db_store_data($query); // Delete link with device type $query = "DELETE FROM werkopdracht_device WHERE werkopdracht=" . $woitem_id; db_store_data($query); // Delete item prices $query = "DELETE FROM werkopdracht_kosten WHERE werkopdracht=" . $woitem_id; db_store_data($query); // Delete documentation $query = "SELECT id FROM werkopdracht_documenten WHERE werkopdracht=" . $woitem_id . " FOR UPDATE"; $docs = db_fetch_data($query); if( $docs ) foreach( $docs as $doc ) { db_delete_file($doc['id'], "werkopdracht_documenten"); } // Commit transaction return db_commit_transaction(); } /** * Link workorder item with an equipment type * * Inputs: * - woitem_id Database identifier for the workorder item * - equipment_id Database identifier for the equipement type * - replace Replace current links when TRUE, add to the * current links when FALSE (will generate "duplicate * key" errors for those links that are already in * place and this is intentional) * * Returns: * Boolean (success or failure) */ function db_link_workorder_item($woitem_id, $equipment_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($woitem_id) ) { trigger_error("Numeric workorder item id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM werkopdracht_device WHERE werkopdracht=" . $woitem_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO werkopdracht_device (device,werkopdracht) VALUES "; if( is_array($equipment_id) && count($equipment_id) > 0 ) { foreach( $equipment_id as $device ) { $query .= $sep . "(" . $device . "," . $woitem_id . ")"; $sep = ","; } } else if( is_numeric($equipment_id) ) { $query = $sep . "(" . $equipment_id . "," . $woitem_id . ")"; } else if( $equipment_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Link werkorder items when an equipment type * Complementary to the function above * * - equipment_id Equipment type to link the system components to * - woitem_id Workorder items to link (single or array) * - replace Replace or augment current list * * Returns: * Boolean (success or error) */ function db_link_workorder_items($equipment_id, $woitem_id, $replace) { // Start transaction db_start_transaction(); if( !is_numeric($equipment_id) ) { trigger_error("Numeric equipment id expected", E_USER_ERROR); return FALSE; } if( $replace && !db_store_data("DELETE FROM werkopdracht_device WHERE device=" . $equipment_id) ) { // error return FALSE; } $query = ""; $sep = "INSERT INTO werkopdracht_device (device,werkopdracht) VALUES "; if( is_array($woitem_id) && count($woitem_id) > 0 ) { foreach( $woitem_id as $woitem ) { $query .= $sep . "(" . $equipment_id . "," . $woitem . ")"; $sep = ","; } } else if( is_numeric($woitem_id) ) { $query = $sep . "(" . $equipment_id . "," . $woitem_id . ")"; } else if( $woitem_id ) { // parameter error; note that NULL values, empty strings etc are // allowed and those will effectively remove the current list // of links (when 'replace' is set) or do nothing when adding. return FALSE; } if( $query && !db_store_data($query) ) return FALSE; // Commit transaction return db_commit_transaction(); } /** * Fetch workorders that use a repair item * * Inputs: * - woitem_id Database identifier for the workorder item * * Returns: * An array with workorder identifiers, or FALSE on error */ function db_fetch_linked_workorder_items($woitem_id) { return db_fetch_data("SELECT * FROM zkl_werkorder_werkopdracht WHERE link_table='werkopdracht' AND link_id=" . $woitem_id); } /************************************************************************/ /* */ /* Workorders */ /* */ /************************************************************************/ define("WORKORDER_TIME_INTERVAL", 15 * 60); /** * Get readable identifier for the workorder */ function db_printf_workorder_id($wo) { return "WO" . sprintf("%08u", $wo['nummer']); } /** * Helpers */ // Return all psuedo states function db_workorder_pseudo_status() { return array( "!afgekeurd", // all but rejected workorders "open", // open workorders (not rejected, not completed, not written off, not a client receipt) "controle productie", // new devices "inschrijving", // device is registered for service "offerte", // price quote sent to customer; in-take has taken place, but repairs must be approved by the customer "onder limiet", // total amount for the repairs is under the service limit "boven limiet", // total amount for the repairs is above the service limit "goedgekeurd", // price quote approved "afgekeurd", // price quote (or workorder) rejected "!bezig", // repairs haven't started yet (device is registered and waiting for approval or has been approved) "bezig", // repairs have started "gereedgemeld", // repairs are complete "elek. test", // device is in calibration test ("electronics test") "func. test", // device is at endcontrol ("functional test") "!gereed", // service and maintainance on the device has not yet been completed "gereed", // service and maintainance has been completed "afgeschreven", // device is written off *) "gefactureerd", // invoice has been sent *) "uitgiftebon", // client receipt "gereed|uitgiftebon" // (quite likely) returned to the customer ); // *) states not actively used } // Return all real states, as recorded in the database (excluding "afgeschreven" and "gefactureerd") function db_workorder_real_status() { return array( 'inschrijving', 'offerte', 'goedgekeurd', 'afgekeurd', 'bezig', 'gereedgemeld', 'elek. test', 'func. test', 'gereed', 'uitgiftebon' ); } function db_workorder_status($status) { switch( $status ) { case "controle productie": return "goedgekeurd"; case "boven limiet": case "onder limiet": return "!afgekeurd,!uitgiftebon"; case "open": return "!afgekeurd,!gereed,!afgeschreven,!uitgiftebon"; case "test": return "elek. test,func. test"; case "!bezig": return "inschrijving,offerte,goedgekeurd"; case "!gereed": return "!gereed,!afgeschreven,!afgekeurd,!uitgiftebon"; case "gefactureerd": return "gereed|uitgiftebon"; default: return $status; } } function db_workorder_datefield($status) { switch( $status ) { case "inschrijving": return "datum_inschrijving"; case "offerte": case "wachten": case "opname": case "controle productie": case "uitgiftebon": return "datum_opname"; case "goedgekeurd": case "afgekeurd": return "datum_goedkeuring"; case "bezig": return "datum_start"; case "gereedgemeld": return "datum_gereedmelding"; case "elek. test": return "datum_elek_test"; case "func. test": return "datum_func_test"; case "gereed": case "afgeschreven": return "datum_gereed"; case "gefactureerd": return "datum_factuur"; default: return FALSE; } } function db_workorder_userfield($status) { switch( $status ) { case "inschrijving": return "gebruiker_inschrijving"; case "offerte": case "wachten": case "opname": case "controle productie": case "uitgiftebon": return "gebruiker_opname"; case "goedgekeurd": case "afgekeurd": return "gebruiker_goedkeuring"; case "bezig": return "gebruiker_start"; case "gereedgemeld"; return "gebruiker_gereedmelding"; case "elek. test": return "gebruiker_elek_test"; case "func. test": return "gebruiker_func_test"; case "gereed": case "afgeschreven": return "gebruiker_gereed"; case "gefactureerd": return "gebruiker_factuur"; default: return FALSE; } } function db_workorder_is_ready($status) { return $status == 'gereedgemeld' || $status == 'elek. test' || $status == 'func. test' || $status == 'gereed'; } function db_workorder_is_approved($status) { // return $status >= 'goedgekeurd' return $status == 'goedgekeurd' || $status == 'bezig' || $status == 'gereedgemeld' || $status == 'elek. test' || $status == 'func. test' || $status == 'gereed'; } function db_workorder_is_rejected($status) { return $status == 'afgekeurd'; } function db_workorder_user($wo) { $user = $wo[db_workorder_userfield($wo['status'])]; if( !$user && $wo['status'] == 'goedgekeurd' ) { // automatically approved; find the real user $user = $wo['gebruiker_opname']; } return getUser($user); } function db_workorder_actual_status($wo) { if( $wo['lans_status'] == 'productie' && in_array($wo['status'], array('inschrijving','opname')) ) return 'controle productie'; else return $wo['status']; } /** * Fetch workorders by status * * Input: * - wo_number Workorder number to fetch * - filter Filter options * - lance * - device * - customer * - depot * - status * - sort Sort options (string) * - any field from 'zkl_werkorder' * - "totaal", "totaal_debet" or "totaal_credit" * - "serienr", "idcode" * * Returns: * - An array with matching workorders, with total price */ function db_search_workorders($i18n, $wo_number = NULL, $filter = FALSE, $sort = FALSE) { global $_PAGE_INFO; if( $i18n === TRUE ) { // force the use of the customer's language $select_i18n = "klant.i18n"; } else if( $i18n === FALSE ) { // force the use of the user's language $select_i18n = "'" . $_SESSION[$_PAGE_INFO['id']]['i18n'] . "'"; } else { $select_i18n = "'" . $i18n . "'"; } // First, sort out the filters if( !$filter ) $filter = array(); // prevent warnings below // Determine the applicable date fields // NB: $date_field may be FALSE, in which case the query selects the workorders that // are active between the start and end dates $date_field = FALSE; // by default, select the active workorders if( $filter['begin_date'] || $filter['end_date'] ) { if( !is_array($filter['status']) ) { $date_field = db_workorder_datefield($filter['status']); } else foreach( $filter['status'] as $test ) { // Use the date field applicable for the workorder status, or the generic 'datum' // field when this is ambiguous $date_for_test = db_workorder_datefield($test); if( $date_for_test ) { if( !$date_field ) $date_field = $date_for_test; else $date_field = 'datum'; } } } // Build the WHERE and HAVING clauses $query_where = ""; // $query_where_sep = " WHERE "; // $query_user = FALSE; // (different for the three union queries) $query_user_all = FALSE; // $query_having = ""; // the HAVING clause is optional, so we work $query_having_sep = " HAVING "; // with a seperator that must be prepended // By number? if( is_numeric($wo_number) || (substr($wo_number,0,2) == "WO" && is_numeric($wo_number = substr($wo_number,2))) ) { $query_where .= $query_where_sep . "zkl_werkorder.nummer =" . $wo_number; $query_where_sep = " AND "; } if( $filter['wo_id'] && is_array($filter['wo_id']) ) { $query_where .= $query_where_sep . "zkl_werkorder.id IN (" . implode(",", $filter['wo_id']) . ")"; $query_where_sep = " AND "; } // By lance (database idenfier)? $lance = $filter['lance']; // Set the default lance filter, using the pyramid of customers, unless filtering // on lance if( !$lance ) { $lances = db_search_lances($filter['device']); $default_lances = array(); if( $lances ) foreach ($lances as $lance) { if( !$filter['customer'] || (_is_null($lance['eigenaar']) && in_array("NULL", $filter['customer'])) || in_array($lance['eigenaar'], $filter['customer']) ) { $default_lances[] = $lance['id']; } } $row_customers = db_search_customers(); $default_customers = array(); foreach( $row_customers as $customer ) { $default_customers[] = $customer['id']; } if( !in_array($_PAGE_INFO['login']['customer']['id'], $default_customers) ) { $default_customers[] = $_PAGE_INFO['login']['customer']['id']; } $query_where .= $query_where_sep . "("; $sep = ""; if( $default_lances ) { $query_where .= "zkl_werkorder.zkl IN (" . implode(",", $default_lances) . ")"; $sep = " OR "; } if( $default_customers ) { $query_where .= $sep . "(zkl_werkorder.zkl=0 AND zkl_werkorder.klant IN (" . implode(",", $default_customers) . "))"; } else { $query_where .= $sep . "zkl_werkorder.zkl=0"; } if( $sep ) $query_where .= ")"; $query_where_sep = " AND "; } else if( is_array($lance) ) { if( isset($lance['id']) ) { $query_where .= $query_where_sep . "zkl_werkorder.zkl=" . $lance['id']; $query_where_sep = " AND "; } else if( $lance && ($lances = implode(",", $lance)) ) { $query_where .= $query_where_sep . "zkl_werkorder.zkl IN (" . $lances . ")"; $query_where_sep = " AND "; } } else if( is_numeric($lance) ) { $query_where .= $query_where_sep . "zkl_werkorder.zkl=" . $lance; $query_where_sep = " AND "; } // By device type? (single database identifier only) if( is_array($filter['device']) ) { // empty device filter? return empty result set if( count($filter['device']) > 0 ) { $devices = implode(",", $filter['device']); $query_where .= $query_where_sep; $query_where .= "zkl_werkorder.zkl IN (SELECT id FROM zkl WHERE device IN (" . $devices . "))"; $query_where_sep = " AND "; } } else if( is_numeric($filter['device']) ) { $query_where .= $query_where_sep; $query_where .= "zkl_werkorder.zkl IN (SELECT id FROM zkl WHERE device=" . $filter['device'] . ")"; $query_where_sep = " AND "; } // By customer? (single database identifier only) if( $filter['customer'] ) { $query_where .= $query_where_sep; $query_where .= "("; $query_where .= "zkl_werkorder.klant IN (" . _implode(",", $filter['customer']) . ")"; $query_subquery_sep = " OR "; $query_subquery_sep .= "zkl_werkorder.zkl IN ("; $query_subquery_sep .= "SELECT id"; $query_subquery_sep .= " FROM zkl"; $query_subquery_sep .= " WHERE ("; $query_subquery_end = ""; if( is_array($filter['customer']) ) $customers = $filter['customer']; else $customers = array($filter['customer']); foreach( $customers as $cust ) { $query_where .= $query_subquery_sep; if( _is_null($cust) ) $query_where .= "eigenaar IS NULL"; else $query_where .= "eigenaar=" . $cust; $query_subquery_sep = " OR "; $query_subquery_end = "))"; } $query_where .= $query_subquery_end; $query_where .= ")"; $query_where_sep = " AND "; } // By depot? if( $filter['depot'] ) { $query_subquery_sep = $query_where_sep . "("; $query_subquery_end = ""; if( is_array($filter['depot']) ) $depots = $filter['depot']; else $depots = array($filter['depot']); foreach( $depots as $depot ) { $query_where .= $query_subquery_sep . "zkl_werkorder.depot='" . $depot . "'"; $query_subquery_sep = " OR "; $query_subquery_end = ")"; $query_where_sep = " AND "; } $query_where .= $query_subquery_end; } // filter by status? may be empty... if( $filter['status'] ) { // $status can be an array of statuses, or a comma separated string if( !is_array($filter['status']) ) { $status = explode("|", $filter['status']); } else $status = $filter['status']; $query_where .= $query_where_sep . "(("; $sep = ""; foreach( $status as $test ) { // translate status $test = db_workorder_status($test); foreach( explode(",", $test) as $subtest ) { $query_where .= $sep; if( substr($subtest, 0, 1) == '!' ) { $query_where .= "NOT "; $subtest = substr($subtest, 1); } $query_where .= "zkl_werkorder.status='" . $subtest . "'"; $sep = " AND "; } $sep = ") OR ("; } $query_where .= "))"; $query_where_sep = " AND "; } // On date? if( $filter['begin_date'] ) { $begin_date = $filter['begin_date']; if( $filter['begin_time'] ) $begin_date .= " " . $filter['begin_time']; if( $filter['end_date'] ) { $end_date = $filter['end_date']; if( $filter['end_time'] ) $end_date .= " " . $filter['end_time']; } else $end_data = FALSE; $query_where .= $query_where_sep; $query_where_sep = " AND "; if( $date_field ) { // filtering on status, so we check as specific date field if( $filter['end_date'] ) { $query_where .= "DATE(" . $date_field . ") BETWEEN '" . $begin_date . "' AND '" . $end_date . "'"; } else { $query_where .= "DATE(" . $date_field . ") >= '" . $begin_date . "'"; } } else { // no filter on status: select all active workorders (registered before the end date and // not completed before the begin date) if( $filter['end_date'] ) { $query_where .= "DATE(datum_inschrijving) <= '" . $end_date . "'"; $query_where .= " AND NOT ("; $query_where .= "((zkl_werkorder.status='gereed' OR zkl_werkorder.status='afgeschreven') AND DATE(datum_gereed) < '" . $begin_date . "')"; $query_where .= " OR "; $query_where .= "(zkl_werkorder.status='afgekeurd' AND DATE(datum_goedkeuring) < '" . $begin_date . "')"; $query_where .= ")"; } else { // select all active workorders $query_where .= "DATE(datum_inschrijving) >= '" . $begin_date . "'"; } } } else if( $filter['end_date'] ) { $end_date = $filter['end_date']; if( $filter['end_time'] ) $end_date .= " " . $filter['end_time']; // end date without a start date $query_where .= $query_where_sep; $query_where_sep = " AND "; if( $date_field ) { $query_where .= "DATE(" . $date_field . ") <= '" . $end_date . "'"; } else { // no filter on status: select all workorders active on the end date $query_where .= "DATE(datum_inschrijving) <= '" . $end_date . "'"; } } // Filter on special statuses ('status' is already set as needed) if( $filter['status'] == "boven limiet" ) { $query_having .= $query_having_sep . "("; $query_having .= "(max_bedrag IS NULL AND totaal_debet > 0)"; $query_having .= " OR "; $query_having .= "(max_bedrag > 0 AND totaal_debet > max_bedrag)"; $query_having .= ")"; $query_having_sep = " AND "; } else if( $filter['status'] == "onder limiet" ) { $query_having .= $query_having_sep . "("; $query_having .= "max_bedrag = 0 OR totaal_debet <= max_bedrag"; $query_having .= ")"; $query_having_sep = " AND "; } else if( $filter['status'] == "controle productie" ) { // also "status='goedgekeurd'" $query_where .= $query_where_sep . " zkl_werkorder.lans_status='productie'"; $query_where_sep = " AND "; } else if( $filter['status'] == "gefactureerd" ) { $query_where .= $query_where_sep . " datum_factuur IS NOT NULL"; $query_where_sep = " AND "; } // Total price non zero? if( $filter['totaal_debet'] === TRUE ) { $query_having .= $query_having_sep; if( $filter['debet_credit'] ) $query_having .= "(nr_repair_items > 0 AND totaal != 0)"; else $query_having .= "totaal_debet != 0"; $query_having_sep = " AND "; } // Filter on currency if( $filter['valuta'] ) { $query_where .= $query_where_sep; $query_where .= "zkl_werkorder.valuta='" . $filter['valuta'] . "'"; $query_where_sep = " AND "; } // User if( isset($filter['user']) ) { $query_subquery_sep = $query_where_sep . "("; $query_subquery_end = ""; if( is_array($filter['user']) ) $users = $filter['user']; else $users = array($filter['user']); foreach( $users as $user ) if( is_numeric($user) ) { $query_where .= $query_subquery_sep; $query_subquery_sep = " OR "; $query_subquery_end = ")"; if( db_workorder_userfield($filter['status']) ) { $query_where .= db_workorder_userfield($filter['status']) . "=" . $user; } else { $query_where .= "gebruiker_inschrijving=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_opname=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_offerte=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_goedkeuring=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_start=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_gereedmelding=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_elek_test=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_func_test=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_gereed=" . $user; $query_where .= " OR "; $query_where .= "gebruiker_factuur=" . $user; } $query_where .= " OR (zkl_werkorder_werkopdracht.id IS NOT NULL AND zkl_werkorder_werkopdracht.id IN (SELECT id FROM zkl_werkorder_werkopdracht WHERE gebruiker=" . $user . "))"; $query_where_sep = " AND "; } $query_where .= $query_subquery_end; } // Textual filter if( $filter['text'] ) { $query_where .= $query_where_sep; $query_where .= "("; $query_where .= "zkl_werkorder.nummer LIKE '%" . $filter['text'] . "%'"; $query_where .= " OR zkl_werkorder.zkl IN ("; $query_where .= "SELECT id"; $query_where .= " FROM zkl"; $query_where .= " WHERE "; $query_where .= "idcode LIKE '%" . $filter['text'] . "%'"; $query_where .= " OR "; $query_where .= "serienr LIKE '%" . $filter['text'] . "%'"; $query_where .= ")"; $query_where .= ")"; $query_where_sep = " AND "; } $query = "SELECT zkl_werkorder.*,"; $query .= "DATE(IF(zkl_werkorder.status='inschrijving',datum_inschrijving,IF(zkl_werkorder.status='offerte' OR zkl_werkorder.status='uitgiftebon' OR (zkl_werkorder.status='goedgekeurd' AND zkl_werkorder.lans_status='productie'),datum_opname,IF(zkl_werkorder.status='goedgekeurd' OR zkl_werkorder.status='afgekeurd',datum_goedkeuring,IF(zkl_werkorder.status='bezig',datum_start,IF(zkl_werkorder.status='gereedgemeld',datum_gereedmelding,IF(zkl_werkorder.status='elek. test',datum_elek_test,IF(zkl_werkorder.status='func. test',datum_func_test,datum_gereed)))))))) AS datum,"; $query .= "IF(zkl_werkorder.status='inschrijving',gebruiker_inschrijving,IF(zkl_werkorder.status='offerte' OR zkl_werkorder.status='uitgiftebon' OR (zkl_werkorder.status='goedgekeurd' AND zkl_werkorder.lans_status='productie'),gebruiker_opname,IF(zkl_werkorder.status='goedgekeurd' OR zkl_werkorder.status='afgekeurd',gebruiker_goedkeuring,IF(zkl_werkorder.status='bezig',gebruiker_start,IF(zkl_werkorder.status='gereedgemeld',gebruiker_gereedmelding,IF(zkl_werkorder.status='elek. test',gebruiker_elek_test,IF(zkl_werkorder.status='func. test',gebruiker_func_test,gebruiker_gereed))))))) AS gebruiker,"; $query .= "COUNT(zkl_werkorder_werkopdracht.id) AS nr_repair_items,"; $query .= "IF(COUNT(zkl_werkorder_werkopdracht.id)=0,0.00,SUM(zkl_werkorder_werkopdracht.bedrag * zkl_werkorder_werkopdracht.aantal)) AS totaal,"; $query .= "IF(COUNT(zkl_werkorder_werkopdracht.id)=0,0.00,SUM((zkl_werkorder_werkopdracht.credit != '' OR zkl_werkorder_werkopdracht.status = 'overgeslagen') * zkl_werkorder_werkopdracht.bedrag * zkl_werkorder_werkopdracht.aantal)) AS totaal_credit,"; $query .= "IF(COUNT(zkl_werkorder_werkopdracht.id)=0,0.00,SUM((zkl_werkorder_werkopdracht.credit = '' AND zkl_werkorder_werkopdracht.status != 'overgeslagen') * zkl_werkorder_werkopdracht.bedrag * zkl_werkorder_werkopdracht.aantal)) AS totaal_debet,"; $query .= "device_service_limits.bedrag AS max_bedrag,"; $query .= "IF(SUM((zkl_werkorder_werkopdracht.credit = '' AND zkl_werkorder_werkopdracht.status != 'overgeslagen') * zkl_werkorder_werkopdracht.bedrag * zkl_werkorder_werkopdracht.aantal) > 0,(SUM((zkl_werkorder_werkopdracht.credit = '' AND zkl_werkorder_werkopdracht.status != 'overgeslagen') * zkl_werkorder_werkopdracht.bedrag * zkl_werkorder_werkopdracht.aantal) - IF(device_service_limits.bedrag IS NOT NULL,device_service_limits.bedrag,0.00)),0.00) AS limiet_sortorder,"; $query .= "IF(zkl_werkorder.status='goedgekeurd' AND zkl_werkorder.lans_status='productie',0,zkl_werkorder.status + 0) AS status_sortorder,"; $query .= "zkl.serienr,"; $query .= "zkl.idcode,"; $query .= "klant.bedrijfsnaam,"; $query .= "device_name.naam AS devicenaam"; $query .= " FROM zkl_werkorder"; $query .= " LEFT OUTER JOIN zkl_werkorder_werkopdracht ON ("; $query .= "zkl_werkorder.id=zkl_werkorder_werkopdracht.zkl_werkorder"; $query .= ")"; $query .= " LEFT OUTER JOIN zkl ON ("; $query .= "zkl_werkorder.zkl=zkl.id"; $query .= ")"; $query .= " LEFT OUTER JOIN klant ON ("; $query .= "(zkl_werkorder.klant=klant.id)"; $query .= ")"; $query .= " LEFT OUTER JOIN device_name ON ("; $query .= "zkl.device=device_name.device AND device_name.i18n=" . $select_i18n; $query .= ")"; $query .= " LEFT OUTER JOIN device_service_limits ON ("; $query .= "device_service_limits.device=zkl.device AND "; $query .= "device_service_limits.klant=zkl_werkorder.klant AND "; $query .= "device_service_limits.valuta=zkl_werkorder.valuta"; $query .= ")"; $query .= $query_where; $query .= " GROUP BY zkl_werkorder.id"; $query .= $query_having; if( $sort ) { $query .= " ORDER BY " . $sort; } return db_fetch_data($query); } /** * Count workorders * * Inputs: * - grouping Group by this item; this also determines the array keys * NB: Currently only "status" is allowed (or at least working) * - filter Not (yet?) implemented * Outputs: * - An associate array with a count for each "grouping" on success * - FALSE on error */ function db_count_workorders($grouping, $filter = FALSE) { $query = "SELECT COUNT(*) AS `value`," . $grouping . " AS `key`"; $query .= " FROM zkl_werkorder"; $query .= " GROUP BY " . $grouping; if( !($data = db_fetch_data($query)) ) { // database error return FALSE; } $result = array(); // ensure that the array is fully populated $status_set = db_fetch_set("zkl_werkorder", "status"); foreach( $status_set as $status_item ) $result[$status_item] = 0; // insert the actual data foreach( $data as $row ) { $result[$row['key']] = $row['value']; } return $result; } /** * Fetch workorder repairs * * Outputs: * - col_headers Data for the column headers, matching the columns in the returned data * - row_headers Data for the row headers * Input: * - filter Filter options * - soort_opdracht * - sort Sort options (string) * - any field from 'zkl_werkorder_werkopdracht' * - "artikelnr" * * Returns: * - An array with matching repairs, to be sorted out by the caller */ function db_search_workorder_repairs($i18n, &$col_headers, &$row_headers, $filter = NULL, $sort = NULL) { // modify filter for the needs for the repair list // mechanic set? only when no workorder status is selected if( $filter['user'] && !$filter['status'] ) { $filter['repair_user'] = $filter['user']; unset($filter['user']); } // filter on date? filter on the date of the repairs when no workorder status is selected if( ($filter['begin_date'] || $filter['end_date']) && !$filter['status'] ) { $filter['repair_begin'] = $filter['begin_date']; $filter['repair_end'] = $filter['end_date']; unset($filter['begin_date']); unset($filter['end_date']); } // Some bookkeeping... determine the sort order for the two queries if( !$sort ) $sort = "artikelnr"; $primary_sort = explode(",", $sort); $primary_sort = $primary_sort[0]; switch( $primary_sort ) { case 'artikelnr': $wo_sort = "idcode,nummer"; $repair_sort = $sort; $row_by = "link_id"; $column_by = "zkl"; break; case 'soort_opdracht': $wo_sort = "idcode,nummer"; $repair_sort = "soort_opdracht_by_id,artikelnr"; $row_by = "link_id"; $column_by = "zkl"; break; case 'devicenaam': $wo_sort = $sort; $repair_sort = "artikelnr"; $row_by = "link_id"; $column_by = "zkl"; break; case 'gebruiker': // option: 'ultimo_gebruiker' (when the user for a repair is NULL, // use the user from the in-take, client receipt, etc) $wo_sort = FALSE; $repair_sort = "artikelnr";//"gebruiker"; $row_by = "link_id"; $column_by = "gebruiker"; break; default: // sort order for the workorder query $wo_sort = $sort; $repair_sort = "artikelnr"; $row_by = "link_id"; if( in_array($primary_sort, array('datum','nummer','bedrijfsnaam')) ) { $column_by = $primary_sort; } else { $column_by = "zkl"; } break; } // show each workorder? if( $filter['split_workorder'] ) { $column_by = "nummer"; } // Firstly, get the workorders involved $workorders = db_search_workorders($i18n, NULL, $filter, $wo_sort); // Re-arrange the workorders if( $workorders ) { $workorders_by_id = array(); foreach( $workorders as $workorder ) { $workorders_by_id[$workorder['id']] = $workorder; } $workorders = $workorders_by_id; unset($workorders_by_id); } else { // no matching workorders return FALSE; } // Build the query to fetch the repairs $query_where = ""; // Filter on the type of repair if( $filter['soort_opdracht'] ) { $query_where .= " AND werkopdracht.soort_opdracht='" . $filter['soort_opdracht'] . "'"; } // Do we want items under warrantee? if( $filter['credit'] ) { $query_where .= " AND ("; if( substr($filter['credit'], 0, 1) == '!' ) { $query_where .= "NOT "; $filter['credit'] = substr($filter['credit'], 1); } $query_where .= "zkl_werkorder_werkopdracht.credit='" . $filter['credit'] . "'"; $query_where .= ")"; } // Status if( $filter['repair_status'] ) { $query_where .= " AND ("; if( substr($filter['repair_status'], 0, 1) == '!' ) { $query_where .= "NOT "; $filter['repair_status'] = substr($filter['repair_status'], 1); } $query_where .= "zkl_werkorder_werkopdracht.status='" . $filter['repair_status'] . "'"; $query_where .= ")"; } // On date? Only where not filtering on workorder status if( $filter['repair_begin'] ) { $repair_begin = $filter['repair_begin']; if( $filter['begin_time'] ) $repair_begin .= " " . $filter['begin_time']; if( $filter['repair_end'] ) { $repair_end = $filter['repair_end']; if( $filter['end_time'] ) $repair_end .= " " . $filter['end_time']; } $query_where .= " AND "; // filtering on status, so we check as specific date field if( $filter['repair_end'] ) { $query_where .= "zkl_werkorder_werkopdracht.datum BETWEEN '" . $repair_begin . "' AND '" . $repair_end . "'"; } else { $query_where .= "zkl_werkorder_werkopdracht.datum >= '" . $repair_begin . "'"; } } else if( $filter['repair_end'] ) { $repair_end = $filter['repair_end']; $query_where .= " AND "; $query_where .= "zkl_werkorder_werkopdracht.datum <= '" . $repair_end . "'"; } // On user? if( $filter['repair_user'] ) { if( is_array($filter['repair_user']) ) $users = $filter['repair_user']; else $users = array($filter['repair_user']); $query_subquery_sep .= " AND ("; $query_subquery_end = ""; foreach( $users as $user ) if( is_numeric($user) ) { $query_where .= $query_subquery_sep . "zkl_werkorder_werkopdracht.gebruiker='" . $user . "'"; $query_subquery_sep = " OR "; $query_subquery_end = ")"; } $query_where .= $query_subquery_end; } // Fetch the repairs $query = "SELECT "; $query .= "zkl_werkorder_werkopdracht.*,"; $query .= "IF(zkl_werkorder_werkopdracht.gebruiker IS NULL,IF(zkl_werkorder.status='inschrijving',gebruiker_inschrijving,IF(zkl_werkorder.status='offerte' OR zkl_werkorder.status='uitgiftebon' OR (zkl_werkorder.status='goedgekeurd' AND zkl_werkorder.lans_status='productie'),gebruiker_opname,IF(zkl_werkorder.status='goedgekeurd' OR zkl_werkorder.status='afgekeurd',gebruiker_goedkeuring,IF(zkl_werkorder.status='bezig',gebruiker_start,IF(zkl_werkorder.status='gereedgemeld',gebruiker_gereedmelding,IF(zkl_werkorder.status='elek. test',gebruiker_elek_test,IF(zkl_werkorder.status='func. test',gebruiker_func_test,gebruiker_gereed))))))),zkl_werkorder_werkopdracht.gebruiker) AS ultimo_gebruiker,"; $query .= "zkl_werkorder.nummer,"; $query .= "IF(zkl_werkorder_werkopdracht.credit != '' OR zkl_werkorder_werkopdracht.status = 'overgeslagen','credit','debet') AS debet_credit,"; $query .= "werkopdracht.artikelnr,"; $query .= "werkopdracht.soort_opdracht,"; $query .= "werkopdracht.soort_opdracht + 0 AS soort_opdracht_by_id"; $query .= " FROM zkl_werkorder_werkopdracht"; $query .= " LEFT OUTER JOIN werkopdracht ON ("; $query .= "zkl_werkorder_werkopdracht.link_id=werkopdracht.id"; $query .= ")"; $query .= " LEFT OUTER JOIN zkl_werkorder ON ("; $query .= "zkl_werkorder_werkopdracht.zkl_werkorder=zkl_werkorder.id"; $query .= ")"; $query .= " LEFT OUTER JOIN zkl ON ("; $query .= "zkl_werkorder.zkl=zkl.id"; $query .= ")"; $query .= " WHERE "; $query .= "zkl_werkorder_werkopdracht.link_table='werkopdracht'"; // hm, doesn't do anything in the 'left outer join' $query .= " AND zkl_werkorder_werkopdracht.zkl_werkorder IN ("; $query .= implode(",", array_keys($workorders)); $query .= ")"; $query .= $query_where; if( $repair_sort ) { $query .= " ORDER BY " . $repair_sort; } if( ($repairs = db_fetch_data($query)) === FALSE ) { // database error return FALSE; } // Create the column headers; the workorder are in sort order // Keep track of which columns have data, so we can easily discard the empty rows // (i.e. workorders with only change log items) $col_data = array(); if( in_array($primary_sort, array("datum","gebruiker") ) ) { // Column order is determined by the repairs foreach( $repairs as $repair ) { // fetch the workorder $workorder = $workorders[$repair['zkl_werkorder']]; // determine column header switch( $primary_sort ) { case 'datum': $col_id = $repair['datum']; if( !$col_id ) $col_id = $workorder['datum']; $col_id = substr($col_id, 0, 10); break; case 'gebruiker': $col_id = $repair['gebruiker']; if( !isset($col_headers[$col_id]) ) { if( !is_numeric($repair['gebruiker']) || ($user_name = getUser($repair['gebruiker'])) === FALSE ) $user_name = "-- " . _("Unknown") . " --"; } break; default: $col_id = $workorder[$column_by]; break; }; if( $column_by == 'nummer' ) { $col_id .= "/" . $workorder['nummer']; } // Set the column header if( !isset($col_headers[$col_id]) ) { switch( $primary_sort ) { case 'datum': // arrange by repair, not workorder $col_header = $repair['datum']; if( !$col_header ) $col_header = $workorder['datum']; $col_header = substr($col_header, 0, 10); $col_headers[$col_id] = array('text' => $col_header); break; case 'gebruiker': // arrange by repair, not workorder $col_headers[$col_id] = array('text' => $user_name); break; default: // NB: not used currently $col_headers[$col_id] = array('text' => $col_id); break; } $col_headers[$col_id]['nummer'] = array(); } // Store the workorder(s) involved if( !isset($col_headers[$col_id]['nummer'][$workorder['nummer']]) ) { $col_headers[$col_id]['nummer'][$workorder['nummer']] = db_printf_workorder_id($workorder); } $col_data[$col_id] = FALSE; } // sort the columns, when not already done through the database if( $primary_sort == 'gebruiker' ) { function sort_by_username($a,$b) { return strcmp($a['text'], $b['text']); }; uasort($col_headers, "sort_by_username"); } } else foreach( $workorders as $wo_id => $workorder ) { // Column order is determined by the workorders switch( $column_by ) { case 'datum': $col_id = $workorder['datum']; $col_id = substr($col_id, 0, 10); break; case 'depot': // identify client receipts as something special ('col_id' will be empty) if( ($col_id = $workorder[$column_by]) ) $col_id .= "/" . $workorder['depot']; break; case 'bedrijfsnaam': $col_id = $workorder['zkl'] . "/" . $workorder['bedrijfsnaam']; break; default: $col_id = $workorder[$column_by]; break; } // Set the column header if( !isset($col_headers[$col_id]) ) { switch( $primary_sort ) { case 'datum': // arrange by repair, not workorder $col_header = $workorder['datum']; $col_header = substr($col_header, 0, 10); $col_headers[$col_id] = array('text' => $col_header); break; case 'nummer': $col_headers[$col_id] = array( // display text 'text' => db_printf_workorder_id($workorder), // info about the device, for as far as collected above 'serienr' => $workorder['serienr'], 'idcode' => $workorder['idcode'], 'devicenaam' => $workorder['devicenaam'], 'bedrijfsnaam' => $workorder['bedrijfsnaam'], 'depot' => $workorder['depot'] ); break; default: $col_headers[$col_id] = array( // display text 'text' => $workorder['idcode'], // info about the device, for as far as collected above 'serienr' => $workorder['serienr'], 'idcode' => $workorder['idcode'], 'devicenaam' => $workorder['devicenaam'], 'bedrijfsnaam' => $workorder['bedrijfsnaam'], 'depot' => $workorder['depot'] ); break; } $col_headers[$col_id]['nummer'] = array(); } // Store the workorder(s) involved if( !isset($col_headers[$col_id]['nummer'][$workorder['nummer']]) ) { $col_headers[$col_id]['nummer'][$workorder['nummer']] = db_printf_workorder_id($workorder); } $col_data[$col_id] = FALSE; } // Put the data into a two-dimensional array; set the row headers on the fly $data = array(); $row_headers = array(); if( $filter['debet_credit'] ) { $row_items = array('debet','credit'); $row_default = 'debet'; } else { $row_items = array(''); $row_default = ''; } foreach( $repairs as $repair ) { // when we don't want separate debet/credit rows, skip if the item is credited if( $filter['debet_credit'] || $repair['debet_credit'] == 'debet' ) { $row_id = $repair[$row_by]; $workorder = $workorders[$repair['zkl_werkorder']]; $valuta = $workorder['valuta']; // Row header set? if( !isset($row_headers[$row_id]) ) { $row_headers[$row_id] = $repair; // also initialize the data row $data[$row_default][$row_id] = array(); } // initialize the credit row? if( $filter['debet_credit'] && !isset($data[$row_item = $repair['debet_credit']][$row_id]) ) { $data[$row_item][$row_id] = array(); } // Fill in the columns switch( $primary_sort ) { case "datum": $col_id = $repair['datum']; if( !$col_id ) $col_id = $workorder['datum']; $col_id = substr($col_id, 0, 10); break; case 'depot': // identify client receipts as something special ('col_id' will be empty) if( ($col_id = $workorder[$column_by]) ) $col_id .= "/" . $workorder['depot']; break; case 'gebruiker': $col_id = $repair['gebruiker']; break; case 'bedrijfsnaam': $col_id = $workorder['zkl'] . "/" . $workorder['bedrijfsnaam']; break; default: $col_id = $workorder[$column_by]; break; } if( in_array($primary_sort, array("datum","gebruiker")) ) { if( $column_by == 'nummer' ) { $col_id .= "/" . $workorder['nummer']; } } // this column has data $col_data[$col_id] = TRUE; // the juggling below is necessary to add the data to the 'debet' column and, // if credited, _also_ to the credit column (by with a negated count) foreach( $row_items as $row_item ) { if( $row_item == $row_default || $row_item == $repair['debet_credit'] ) { $repair_item = $repair; // debet/credit? if( $filter['debet_credit'] ) { if( $row_item == 'credit' ) $repair_item['aantal'] = -$repair_item['aantal']; } else { // shouldn't get here as the entire data row is discarded if( $row_item == 'credit' ) $repair_item['aantal'] = 0; } // first item? if( !isset($data[$row_item][$row_id][$col_id]) ) { $data[$row_item][$row_id][$col_id] = array(); } if( !isset($data[$row_item][$row_id][$col_id][$valuta]) ) { $data[$row_item][$row_id][$col_id][$valuta] = array( 'aantal' => 0, 'totaal' => 0.00 ); } // Accumulate the repairs $data[$row_item][$row_id][$col_id][$valuta]['aantal'] += $repair_item['aantal']; $data[$row_item][$row_id][$col_id][$valuta]['totaal'] += $repair_item['aantal'] * $repair_item['bedrag']; } } } } // Remove the empty columns foreach( $col_data as $col_id => $has_data ) if( !$has_data ) unset($col_headers[$col_id]); // Sort the columns if not done so before if( $primary_sort == 'datum' ) { ksort($col_headers); } return $data; } /** * Fetch the depots * * Inputs: * - customer Fetch only the depots for this customer * * Returns: * - An array with the depots */ function db_search_workorder_depots($cust = FALSE) { $query = "SELECT DISTINCT depot"; $query .= " FROM zkl_werkorder"; if( $cust && is_array($cust) ) { if( isset($cust['id']) ) { $query .= " WHERE klant=" . $cust['id']; } else { if( ($cust_list = _implode(",", $cust)) ) { $query .= " WHERE klant IN (" . $cust_list . ")"; } else return FALSE; // empty list } } else if( is_numeric($cust) ) { $query .= " WHERE klant=" . $cust; } else if( _is_null($cust) ) { $query .= " WHERE klant IS NULL"; } $query .= " ORDER BY 1"; if( ($result = db_fetch_data($query)) === FALSE ) { // database error return FALSE; } else { // re-arrange the array $depots = array(); foreach( $result as $depot ) $depots[] = $depot['depot']; return $depots; } } /** * Fetch workorders for a lance * * Input: * - lance database identifier, lance array or array with database * identifiers * - status Status to filter on. * * Returns: * - An array with matching workorders, _excluding_ the repair items */ function db_fetch_lance_workorders($lance, $status = FALSE) { $query = "SELECT * FROM zkl_werkorder"; // get lance identifier ($lance can be a full array or only the id) if( $lance && is_array($lance) ) { if( isset($lance['id']) ) { $query .= " WHERE zkl=" . $lance['id']; } else { $query .= " WHERE zkl IN (" . implode(",", $lance) . ")"; } } else if( is_numeric($lance) ) { $query .= " WHERE zkl=" . $lance; } else return FALSE; // filter by status? if( $status ) { // $status can be an array of statuses, or a comma separated string if( !is_array($status) ) { $status = explode("|", $status); } $query .= " AND (("; $sep = ""; foreach( $status as $test ) { // translate status $test = db_workorder_status($test); foreach( explode(",", $test) as $subtest ) { $query .= $sep; if( substr($subtest, 0, 1) == '!' ) { $query .= "NOT "; $subtest = substr($subtest, 1); } $query .= "status='" . $subtest . "'"; $sep = " AND "; } $sep = ") OR ("; } $query .= "))"; } if( ($werkorder_data = db_fetch_data($query)) === FALSE ) { // database error return FALSE; } // rearrange array when requesting the workorders for multiple devices if( is_array($lance) && !isset($lance['id']) ) { $werkorders_op_zkl = array(); foreach( $werkorder_data as $werkorder ) { $werkorders_op_zkl[$werkorder['zkl']][] = $werkorder; } return $werkorders_op_zkl; } else { return $werkorder_data; } } /** * Fetch versions for a lance * * Input: * - lance * - i18n * - release_type String (database field 'changelog_versie.soort_release') * * Returns: * Array of system versions */ function db_fetch_lance_versions($lance, $i18n = FALSE, $release_type = FALSE) { // get lance identifier ($lance can be a full array or only the id) if( is_array($lance) ) $lance_id = $lance['id']; else $lance_id = $lance; // sanity check if( !is_numeric($lance_id) ) return FALSE; // get device type $query = "SELECT device FROM zkl WHERE id=" . $lance_id; if( ($type = db_fetch_item($query)) === FALSE ) return FALSE; $query = "SELECT changelog_versie.*,syscomp.id AS syscomp,syscomp.versie_item,syscomp.type AS syscomp_type FROM changelog_versie,syscomp,changelog_versie_syscomp"; $query .= " WHERE changelog_versie.id = changelog_versie_syscomp.versie"; $query .= " AND changelog_versie_syscomp.syscomp = syscomp.id"; $query .= " AND syscomp.id IN ("; $query .= "SELECT syscomp FROM device_syscomp"; $query .= " WHERE device = " . $type; $query .= ")"; $query .= " AND changelog_versie.id IN ("; $query .= "SELECT versie FROM device_changelog_versie"; $query .= " WHERE device = " . $type; $query .= ")"; if( $release_type ) $query .= " AND changelog_versie.soort_release='" . $release_type . "'"; if( $release_type == 'productie' ) { $query .= " GROUP BY syscomp.id"; $query .= " ORDER BY datum DESC,versienummer"; } else if( $release_type ) { $query .= " ORDER BY (soort_release + 0),datum ASC,versienummer"; } $data = db_fetch_data($query); if( $data ) { $versions = array(); foreach( $data as $version ) { // fetch change log $version['changelog'] = array(); $changelog = db_fetch_version_changelog($version['id'], $i18n); if( $changelog ) foreach( $changelog as $change ) if( is_array($change['device']) && in_array($type, $change['device']) ) $version['changelog'][$change['id']] = $change; $versions[$version['id']] = $version; } return $versions; } else return FALSE; } /** * Fetch the maximum amount for a repair * * Inputs: * - lance Database identifier or full array * - customer (optional) Database identifier or full array * - currency (optional) Three letter currency code * * Returns: * - Amount when 'lance', 'customer' and 'currency' are specified, or an * tuple ('customer','currency','amount') if not. * - FALSE on error */ function db_fetch_lance_max_amount($lance, $cust = FALSE, $currency = FALSE) { // get lance identifier ($lance can be a full array or only the id) if( is_array($lance) ) $lance_id = $lance['id']; else $lance_id = $lance; // sanity check if( !is_numeric($lance_id) ) return FALSE; // get customer identifier if( is_array($cust) ) $cust_id = $cust['id']; else $cust_id = $cust; $query = "SELECT "; $query .= "zkl.eigenaar AS klant,"; $query .= "device_service_limits.valuta AS valuta,"; $query .= "device_service_limits.bedrag AS bedrag"; $query .= " FROM "; $query .= "zkl"; $query .= " LEFT OUTER JOIN device_service_limits ON ("; $query .= "device_service_limits.device=zkl.device AND "; $query .= "device_service_limits.klant=zkl.eigenaar"; if( $currency ) $query .= " AND device_service_limits.valuta='" . $currency . "'"; $query .= ")"; $query .= " WHERE zkl.id=" . $lance_id; $sep = " HAVING "; if( is_numeric($cust_id) ) { $query .= $sep . " klant=" . $cust_id; $sep = " AND "; } else if( _is_null($cust_id) ) { $query .= $sep . " klant IS NULL"; $sep = " AND "; } $data = db_fetch_data($query); if( !$data ) { return NULL; // no limit set } else if( (is_numeric($cust_id) || _is_null($cust_id)) && $currency ) { // specific amount requested, so return only that amount return $data[0]['bedrag']; } else { // return array return $data; } } // Idem for equipment type, for use in the entry page only // The parameters are database identifiers function db_fetch_device_max_amount($device_id, $cust_id, $currency = FALSE) { $query = "SELECT *"; $query .= " FROM device_service_limits"; $query .= " WHERE "; $query .= "device=" . $device_id; if( _is_null($cust_id) ) $query .= " AND klant IS NULL"; else if( is_numeric($cust_id) ) $query .= " AND klant=" . $cust_id; if( $currency ) $query .= " AND valuta='" . $currency . "'"; return db_fetch_data($query); } // Fetch insured items function db_fetch_device_insurance($device_id, $cust_id) { $query = "SELECT * FROM device_werkopdracht_fleetservice"; $sep = " WHERE "; if( is_numeric($device_id) ) { $query .= $sep . "device=" . $device_id; $sep = " AND "; } if( _is_null($cust_id) ) { $query .= $sep . "klant IS NULL"; // $sep = " AND "; } else if( is_numeric($cust_id) ) { $query .= $sep . "klant=" . $cust_id; // $sep = " AND "; } return db_fetch_data_array("werkopdracht", $query); } // Fetch fleetservice items function db_fetch_woitem_fleetservice() { $query = "SELECT * FROM werkopdracht"; $query .= " WHERE `fleetservice`='yes'"; return db_fetch_data_array("id", $query); } /** * Store or update the maximum amount for a repair * * Inputs: * - lance_id Database identifier * - customer_id Database identifier * - currency Three letter currency code * - amount Amount to set */ function db_update_lance_max_amount($lance_id, $cust_id, $currency, $amount) { $query = "REPLACE INTO zkl_service_limits"; $query .= " (zkl,klant,valuta,bedrag)"; $query .= " VALUES ("; $query .= $lance_id . ","; if( is_null($cust_id) ) $query .= "NULL" . ","; else $query .= $cust_id . ","; $query .= "'" . $currency . "'" . ","; $query .= $amount; $query .= ")"; return db_store_data($query); } // Idem for equipment type function db_update_device_max_amount($device_id, $cust_id, $currency, $amount) { // Start transaction db_start_transaction(); // Delete and re-insert db_store_data("DELETE FROM `device_service_limits` WHERE `device`=" . $device_id . " AND `klant`=". $cust_id . " AND `valuta`='" . $currency . "'"); // Insert, or not when the limit is cleared // NB: limit==0 is permitted and indicates "infinite" if( is_numeric($amount) ) { $query = "INSERT INTO `device_service_limits`"; $query .= " (`device`,`klant`,`valuta`,`bedrag`)"; $query .= " VALUES ("; $query .= $device_id . ","; if( is_null($cust_id) ) $query .= "NULL" . ","; else $query .= $cust_id . ","; $query .= "'" . $currency . "'" . ","; $query .= $amount; $query .= ")"; if( !db_store_data($query) ) return FALSE; } // Commit if( !db_commit_transaction() ) return FALSE; return TRUE; } // Update insured repairs // NB: on 20140930 it was decided that "fleetservice" and "insurance" are to separate // things (the fleetservice is a property of the workorder/repair item and the // insurance is per customer, on a workorder/repair item; the table name still has // 'fleetservice' in it) function db_update_device_insurance($device_id, $cust_id, $woitem_ids) { // Start transaction db_start_transaction(); // Delete and re-insert the repair items db_store_data("DELETE FROM `device_werkopdracht_fleetservice` WHERE `device`=" . $device_id . " AND `klant`=". $cust_id); // Insert the upgrades, changes to apply and repairs $sep = "INSERT INTO `device_werkopdracht_fleetservice`"; $sep .= " (`device`,`klant`,`werkopdracht`)"; $sep .= " VALUES "; $query = ""; foreach( $woitem_ids as $woitem_id ) { $query .= $sep . "("; $query .= $device_id .","; if( is_null($cust_id) ) $query .= "NULL" . ","; else $query .= $cust_id . ","; $query .= $woitem_id; $query .= ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Commit if( !db_commit_transaction() ) return FALSE; return TRUE; } /** * Fetch all changes already already applied to the lance * * Input: * - lance * - type 'repair', 'change' of 'upgrade' * * Returns: * Array with database identifiers for the applied changes */ function db_fetch_lance_applied_changes($lance, $type) { // get lance identifier ($lance can be a full array or only the id) if( is_array($lance) ) $lance_id = $lance['id']; else $lance_id = $lance; if( !is_numeric($lance_id) ) return FALSE; // translation table from link type to table $linked_table = array( 'repair' => 'werkopdracht', 'change' => 'changelog_versie_change', 'upgrade' => 'changelog_versie' ); $query = "SELECT zkl_werkorder_werkopdracht.link_id AS id"; $query .= " FROM zkl_werkorder_werkopdracht,zkl_werkorder"; $query .= " WHERE zkl_werkorder_werkopdracht.zkl_werkorder=zkl_werkorder.id"; $query .= " AND zkl_werkorder.zkl=" . $lance_id; $query .= " AND zkl_werkorder_werkopdracht.link_table='" . $linked_table[$type] . "'"; $query .= " AND zkl_werkorder_werkopdracht.status='gereed'"; $data = db_fetch_data($query); if( $data ) { $result = array(); foreach( $data as $change ) $result[] = $change['id']; return $result; } else return FALSE; } /** * Fetch all possible repair items for a lance * * Input: * - lance * - i18n * - currentcy * * Returns: * Array of repair/workorder items */ function db_fetch_lance_workorder_items($lance, $i18n = FALSE, $currency = FALSE, $order = FALSE) { // get lance identifier ($lance can be a full array or only the id) $lance_id = $lance; if( is_array($lance) && isset($lance['id']) ) $lance_id = $lance['id']; $query = "SELECT werkopdracht.*,werkopdracht_kosten.bedrag,werkopdracht_kosten.valuta"; $query .= " FROM werkopdracht,werkopdracht_device,werkopdracht_kosten"; $query .= " WHERE werkopdracht.id = werkopdracht_device.werkopdracht"; $query .= " AND werkopdracht.id = werkopdracht_kosten.werkopdracht"; if( $currency ) $query .= " AND werkopdracht_kosten.valuta='" . $currency . "'"; if( $lance_id ) { $query .= " AND werkopdracht_device.device IN ("; $query .= "SELECT device FROM zkl WHERE id IN (" . _implode(",", $lance_id) . ")"; $query .= ")"; } if( $order ) $query .= " ORDER BY " . $order; $data = db_fetch_data($query); if( $data ) { // re-order the items $woitems = array(); foreach( $data as $woitem ) { // fetch the item's name if( $i18n ) { $woitem['naam'] = db_fetch_workorder_item_name($woitem['id'], $i18n); $woitem['uitleg'] = db_fetch_workorder_item_explanation($woitem['id'], $i18n); } $woitems[$woitem['id']] = $woitem; } return $woitems; } else return FALSE; } /** * Fetch a workorder * * Inputs: * - dbid Database identifier for the workorder * * Returns: * - The workorder (array) */ function db_fetch_workorder($wo_id) { global $_PAGE_INFO; // Fetch workorder $wo = db_fetch_data("SELECT * FROM zkl_werkorder WHERE id=" . $wo_id); if( !$wo ) return FALSE; else { $wo = $wo[0]; } // Fetch timer(s) first (if any) $query = "SELECT *"; $query .= " FROM zkl_werkorder_werkopdracht_stopwatch"; $query .= " WHERE zkl_werkorder_werkopdracht IN ("; $query .= "SELECT id FROM zkl_werkorder_werkopdracht"; $query .= " WHERE zkl_werkorder=" . $wo_id; $query .= ")"; if( ($data = db_fetch_data($query)) ) { // re-arrange the data $timers = array(); foreach( $data as $timer ) if( $timer['start'] ) $timers[$timer['zkl_werkorder_werkopdracht']] = $timer; } // Translation table from table to link type $link_type = array( 'werkopdracht' => 'repair', 'changelog_versie_change' => 'change', 'changelog_versie' => 'upgrade' ); // Fetch upgrades, changes to apply and repairs and merge in the timers // Put them in an associative array, index by 'link_table' and 'link_id' $query = "SELECT *"; $query .= " FROM zkl_werkorder_werkopdracht"; $query .= " WHERE zkl_werkorder=" . $wo_id; $repair_items = db_fetch_data($query); if( $repair_items ) foreach( $repair_items as $repair ) { $repair['enabled'] = TRUE; if( $timers[$repair['id']] ) { $repair['start'] = $timers[$repair['id']]['start']; $repair['gebruiker'] = $timers[$repair['id']]['gebruiker']; $repair['page_id'] = $timers[$repair['id']]['page']; } $wo[$link_type[$repair['link_table']]][$repair['link_id']] = $repair; } return $wo; } /** * Create a new workorder * * Inputs: * - wo Workorder: an array with the items entered * in MTinfo (depot, gps, user info) * * Returns: * - Database identifier on success, or FALSE on error * - Database identifier is inserted into the input array 'wo' * * Note: * - The comments/remarks must be stored with 'db_update_workorder_comment' */ function db_store_new_workorder(&$wo) { global $_PAGE_INFO; // Start transaction db_start_transaction(); // New workorder; get a unique number for it $date = strtotime($wo['datum_inschrijving']); $query = "SELECT nummer"; $query .= " FROM zkl_werkorder_nummer"; $query .= " WHERE jaar=" . date("Y", $date); $query .= " FOR UPDATE"; $wo_last = db_fetch_item($query); // NB: will set the first workorder of the year to 'yy000001' automatically $wo['nummer'] = sprintf("%02u%06u", date('y', $date), $wo_last + 1); $query = "INSERT INTO `zkl_werkorder`"; $query .= " ("; $query .= "`nummer`,`zkl`,`lans_status`,`klant`,`valuta`,"; $query .= "`gebruiker_inschrijving`,`datum_inschrijving`,"; $query .= "`depot`,"; if( is_numeric($wo['latitude']) && is_numeric($wo['longitude']) ) $query .= "`latitude`,`longitude`,"; $query .= "`status`"; $query .= ")"; $query .= " VALUES ("; $query .= $wo['nummer'] . ","; $query .= $wo['zkl'] . ","; $query .= "'" . $wo['lans_status'] . "'" . ","; if( is_numeric($wo['klant']) ) $query .= $wo['klant'] . ","; else $query .= "NULL" . ","; $query .= "'" . $wo['valuta'] . "'" . ","; $query .= "'" . $wo['gebruiker_inschrijving'] . "'" . ","; $query .= "'" . $wo['datum_inschrijving'] . "'" . ","; if( !isset($wo['depot']) ) { $query .= "NULL" . ","; } else { $query .= "'" . $wo['depot'] . "'" . ","; } if( is_numeric($wo['latitude']) && is_numeric($wo['longitude']) ) { $query .= $wo['latitude'] . "," . $wo['longitude'] . ","; } $query .= "'inschrijving'" ; $query .= ")"; if( !db_store_data($query) ) return FALSE; // Save identifier for the new workorder and return it $wo['id'] = db_fetch_last_id(); // Update last number $query = "REPLACE INTO zkl_werkorder_nummer (jaar,nummer) VALUES ("; $query .= date("Y", $date) . ","; $query .= ($wo['nummer'] % 1000000) ; $query .= ")"; db_store_data($query); // Commit if( !db_commit_transaction() ) return FALSE; return $wo['id']; } /** * Update a workorder * * Inputs: * - wo Workorder: an array with the items selected (checked) * in MTinfo and database identifier for the workorder * * Returns: * - Database identifier on success, or FALSE on error * * Note: * - Only the remarks are updated. All other information is untouched */ function db_update_workorder_comment($wo) { $query = "UPDATE zkl_werkorder"; $query .= " SET"; // `status' must be updated separately $query .= " `opmerking_int`='" . specialchars($wo['opmerking_int']) . "'" . ","; $query .= " `opmerking_ext`='" . specialchars($wo['opmerking_ext']) . "'" ; $query .= " WHERE `id`=" . $wo['id']; if( !db_store_data($query) ) return FALSE; return $wo['id']; } /** * Update the date of registration and the depot (manager option) * * - wo Workorder: an array with the items selected (checked) * in MTinfo * * Returns: * - Database identifier on success, or FALSE on error */ function db_update_workorder_registration($wo) { $query = "UPDATE zkl_werkorder"; $query .= " SET"; $query .= " `datum_inschrijving`='" . $wo['datum_inschrijving'] . "',"; $query .= " `depot`='" . $wo['depot'] . "'"; $query .= " WHERE id=" . $wo['id']; if( !db_store_data($query) ) return FALSE; return $wo['id']; } /** * Update a workorder after intake * * Inputs: * - wo Workorder: an array with the items selected (checked) * in MTinfo * - is_intake In-take or update items if FALSE * * Returns: * - Database identifier on success, or FALSE on error * * Note: * - The workorder already exists (it was created after the registration * step) do this function is actually an update. * - The comments/remarks must be stored with 'db_update_workorder_comment' */ function db_update_workorder_intake($wo, $is_intake) { global $_PAGE_INFO; // Start transaction db_start_transaction(); if( $is_intake ) { // Set user info $query = "UPDATE zkl_werkorder"; $query .= " SET"; $query .= " `gebruiker_opname`='" . $wo['gebruiker_opname'] . "',"; $query .= " `datum_opname`='" . $wo['datum_opname'] . "'"; $query .= " WHERE id=" . $wo['id']; if( !db_store_data($query) ) return FALSE; } // Delete and re-insert the repairs etc db_store_data("DELETE FROM `zkl_werkorder_werkopdracht` WHERE `zkl_werkorder`=" . $wo['id']); // Insert the upgrades, changes to apply and repairs $sep = "INSERT INTO `zkl_werkorder_werkopdracht`"; $sep .= " (`zkl_werkorder`,`link_table`,`link_id`,`credit`,`status`,`aantal`,`bedrag`)"; $sep .= " VALUES "; $query = ""; if( $wo['upgrade'] ) foreach( $wo['upgrade'] as $link_id => $item) { $query .= $sep . "("; $query .= $wo['id'] . ","; $query .= "'changelog_versie'" . ","; $query .= $link_id . ","; $query .= "'" . $item['credit'] . "'" . ","; $query .= "'open'" . ","; $query .= $item['aantal'] . ","; $query .= $item['bedrag'] ; $query .= ")"; $sep = ","; } if( $wo['change'] ) foreach( $wo['change'] as $link_id => $item) { $query .= $sep . "("; $query .= $wo['id'] . ","; $query .= "'changelog_versie_change'" . ","; $query .= $link_id . ","; $query .= "'" . $item['credit'] . "'" . ","; $query .= "'open'" . ","; $query .= $item['aantal'] . ","; $query .= $item['bedrag'] ; $query .= ")"; $sep = ","; } if( $wo['repair'] ) foreach( $wo['repair'] as $link_id => $item) { $query .= $sep . "("; $query .= $wo['id'] . ","; $query .= "'werkopdracht'" . ","; $query .= $link_id . ","; $query .= "'" . $item['credit'] . "'" . ","; $query .= "'open'" . ","; $query .= $item['aantal'] . ","; $query .= $item['bedrag'] ; $query .= ")"; $sep = ","; } if( $query && !db_store_data($query) ) return FALSE; // Commit if( !db_commit_transaction() ) return FALSE; return $wo['id']; } /** * Update the status for a workorder * * Inputs: * - wo The workorder, with the correct user info and date/time * - status * * Returns: * - Database identifier on success, or FALSE on error * * Note: * - The status in the workorder is updated */ function db_update_workorder_status(&$wo, $status) { global $_PAGE_INFO; $query = "UPDATE zkl_werkorder"; $query .= " SET"; switch( $status ) { case 'bezig': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_start`='" . $wo['datum_start'] . "'"; $query .= ",`gebruiker_start`='" . $wo['gebruiker_start'] . "'"; break; case 'gereedgemeld': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_gereedmelding`='" . $wo['datum_gereedmelding'] . "'"; $query .= ",`gebruiker_start`='" . $wo['gebruiker_start'] . "'"; break; case 'elek. test': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_elek_test`='" . $wo['datum_elek_test'] . "'"; $query .= ",`gebruiker_elek_test`='" . $wo['gebruiker_elek_test'] . "'"; break; case 'func. test': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_func_test`='" . $wo['datum_func_test'] . "'"; $query .= ",`gebruiker_func_test`='" . $wo['gebruiker_func_test'] . "'"; break; case 'gereed': case 'afgeschreven': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_gereed`='" . $wo['datum_gereed'] . "'"; $query .= ",`gebruiker_gereed`=" . $wo['gebruiker_gereed']; break; case 'goedgekeurd': case 'afgekeurd': $query .= " `status`='" . ($wo['status'] = $status) . "'"; $query .= ",`datum_goedkeuring`='" . $wo['datum_goedkeuring'] . "'"; $query .= ",`gebruiker_goedkeuring`=" . $wo['gebruiker_goedkeuring']; break; case 'opname': // in-take is not recorded as such but as a price quote (fall-through...) $status = 'offerte'; case 'offerte': case 'uitgiftebon': $query .= " `status`='" . ($wo['status'] = $status) . "'"; if( $wo['datum_wijziging'] ) { // date and user are only mandatory when indeed generating a price // quote as PDF $query .= ",`datum_wijziging`='" . $wo['datum_wijziging'] . "'"; $query .= ",`gebruiker_wijziging`=" . $wo['gebruiker_wijziging']; } else { if( $wo['datum_opname'] ) { $query .= ",`datum_opname`='" . $wo['datum_opname'] . "'"; $query .= ",`gebruiker_opname`=" . $wo['gebruiker_opname']; } if( $wo['datum_offerte'] ) { // date and user are only mandatory when indeed generating a price // quote as PDF $query .= ",`datum_offerte`='" . $wo['datum_offerte'] . "'"; $query .= ",`gebruiker_offerte`=" . $wo['gebruiker_offerte']; } } break; case 'factuur': $query .= ",`datum_factuur`='" . $wo['datum_factuur'] . "'"; $query .= ",`gebruiker_factuur`='" . $wo['gebruiker_factuur'] . "'"; break; default: return FALSE; } $query .= " WHERE `id`=" . $wo['id']; if( !db_store_data($query) ) return FALSE; return $wo['id']; } /** * Update the warrantee status of a repair item in a workorder * * Inputs: * - wo The workorder, with the correct user info and date/time * * Returns: * - Database identifier on success, or FALSE on error */ function db_update_workorder_warrantee($wo) { global $_PAGE_INFO; // Start transaction db_start_transaction(); // Update each item's warrantee status $link_table = array( 'upgrade' => "changelog_versie", 'change' => "changelog_versie_change", 'repair' => "werkopdracht" ); foreach( array('upgrade','change','repair') as $repair_type ) { if( $wo[$repair_type] ) foreach( $wo[$repair_type] as $link_id => $item) { $query = "UPDATE `zkl_werkorder_werkopdracht`"; $query .= " SET `credit`='" . $item['credit'] . "'"; $query .= " WHERE "; $query .= "`zkl_werkorder`=" . $wo['id']; $query .= " AND "; $query .= "`link_table`='" . $link_table[$repair_type] . "'"; $query .= " AND "; $query .= "`link_id`=" . $link_id; db_store_data($query); } } // Commit if( !db_commit_transaction() ) return FALSE; return $wo['id']; } /** * Update a repair item in a workorder * * Inputs: * - wo Full workorder by reference; repair item will be updated * * Returns: * - Database identifier on success, or FALSE on error */ function db_update_workorder_repair(&$wo, $repair_type, $link_id, $repair_item) { $wo_id = $wo['id']; $link_table = array( 'upgrade' => "changelog_versie", 'change' => "changelog_versie_change", 'repair' => "werkopdracht" ); $query = "UPDATE zkl_werkorder_werkopdracht"; $query .= " SET"; if( $repair_item['credit'] ) $query .= " `credit`='" . $repair_item['credit'] . "'" . ","; if( $repair_item['status'] ) $query .= " `status`='" . $repair_item['status'] . "'" . ","; if( is_numeric($repair_item['gebruiker']) ) $query .= " `gebruiker`=" . $repair_item['gebruiker'] . ","; else $query .= " `gebruiker`=NULL" . ","; if( $repair_item['datum'] ) $query .= " `datum`='" . $repair_item['datum'] . "'" . ","; else $query .= " `datum`=NULL" . ","; if( strlen($repair_item['duur']) ) $query .= " `duur`=" . $repair_item['duur'] . ","; else $query .= " `duur`=NULL" . ","; $query .= " `opmerking_int`='" . specialchars($repair_item['opmerking_int']) . "'"; // external remarks are currently not implemented //$query .= " `opmerking_ext`='" . specialchars($repair_item['opmerking_ext']) . "'"; $query .= " WHERE "; $query .= "`zkl_werkorder`=" . $wo_id; $query .= " AND "; $query .= "`link_table`='" . $link_table[$repair_type] . "'"; $query .= " AND "; $query .= "`link_id`=" . $link_id; if( !db_store_data($query) ) return FALSE; else $wo[$repair_type][$link_id] = $repair_item; return $repair_item['id']; } /** * Add a document to this workorder * * Inputs: * - wo_id Database identifier for the workorder * - doc The document, a full array; the 'doc_type' must be * 'werkorder', 'offerte' or 'factuur' */ function db_add_workorder_zkl_document($wo_id, $doc) { $query = "INSERT INTO `zkl_werkorder_zkl_documenten`"; $query .= " (`zkl_werkorder`, `doc_id`, `doc_type`)"; $query .= " VALUES ("; $query .= $wo_id . ","; $query .= $doc['id'] . ","; $query .= "'" . $doc['doc_type'] . "'"; $query .= ")"; return db_store_data($query); } /** * Fetch PDF for a workorder * * Inputs: * - wo_id * - doc_type * * Returns: * - identifier for the document, or FALSE on error */ function db_fetch_workorder_zkl_document($wo_id, $doc_type) { $query = "SELECT MAX(`doc_id`) AS `doc_id`"; $query .= " FROM `zkl_werkorder_zkl_documenten`"; $query .= " WHERE `zkl_werkorder`=" . $wo_id; $query .= " AND `doc_type`='" . $doc_type . "'"; $query .= " GROUP BY `doc_type`,`zkl_werkorder`"; return db_fetch_item($query); } /** * Start and stop the timer for a repair item * * Inputs: * - repair_item Full array or database identifier * * Returns: * Duration in 15 minute intervals or FALSE on error * * Note: * Will overwrite a previous timer (shouldn't happen though; the web * script must prevent this) */ function db_start_workorder_timer($repair_item) { global $_PAGE_INFO; if( is_array($repair_item) ) { $id = $repair_item['id']; $uid = $repair_item['gebruiker']; } else if( is_numeric($repair_item) ) { $id = $repair_item; $uid = $_PAGE_INFO['login']['user']['id']; } else return FALSE; $query = "REPLACE INTO zkl_werkorder_werkopdracht_stopwatch"; $query .= " (zkl_werkorder_werkopdracht,gebruiker,page,start)"; $query .= " VALUES ("; $query .= $id .","; $query .= $uid . ","; $query .= "'" . $_PAGE_INFO['id'] . "',"; $query .= "UNIX_TIMESTAMP()"; $query .= ")"; if( !db_store_data($query) ) return FALSE; // just started... we promissed to return the interval, so there you // go, even though the caller must test for FALSE to see if all went // okay return 0; } function db_stop_workorder_timer($repair_item) { if( is_array($repair_item) ) { $id = $repair_item['id']; $uid = $repair_item['gebruiker']; } else if( is_numeric($repair_item) ) { global $_PAGE_INFO; $id = $repair_item; $uid = $_PAGE_INFO['login']['user']['id']; } else return FALSE; // Start transaction db_start_transaction(); $query = "SELECT UNIX_TIMESTAMP() - start"; $query .= " FROM zkl_werkorder_werkopdracht_stopwatch"; $query .= " WHERE zkl_werkorder_werkopdracht=" . $id; $query .= " AND gebruiker=" . $uid; $query .= " FOR UPDATE"; if( ($duration = db_fetch_item($query)) !== FALSE ) { // remove the entry $query = "DELETE FROM zkl_werkorder_werkopdracht_stopwatch"; $query .= " WHERE zkl_werkorder_werkopdracht=" . $id; $query .= " AND gebruiker=" . $uid; db_store_data($query); } // Commit if( !db_commit_transaction() ) return FALSE; return $duration; } function db_update_workorder_duration($repair_item) { if( is_array($repair_item) ) { $id = $repair_item['id']; $uid = $repair_item['gebruiker']; } else if( is_numeric($repair_item) ) { global $_PAGE_INFO; $id = $repair_item; $uid = $_PAGE_INFO['login']['user']['id']; } else return FALSE; $query = "UPDATE zkl_werkorder_werkopdracht"; $query .= " SET duur=" . $repair_item['duur']; $query .= " WHERE id=" . $id; return db_store_data($query); } /** * Send price quotation via e-mail * * Inputs: * - msg_type Which message to send * - wo Workorder * - recipients List of recipients (user id's) * - file PDF document */ function db_workorder_send_mail($msg_type, $wo, $recipients, $file = NULL) { global $_PAGE_INFO; $i18n_user = $_SESSION[$_PAGE_INFO['id']]['i18n']; // Collect the users $users = array(); if( !is_array($recipients) ) $recipients = explode(",", $recipients); foreach( $recipients as $recipient ) { if( is_array($recipient) ) { // assuming full array $users[] = $recipient; } else if( is_numeric($recipient) ) { // database identifier $users[] = db_fetch_user($recipient, NULL, TRUE); } else return FALSE; } if( !$users ) return FALSE; // Get lance info $row_lance = db_fetch_lance($_SESSION[$_PAGE_INFO['id']]['wo_info']['zkl'], "", 1); // Collect the languages in which to send the e-mails and abstract the e-mail addresses $email = array(); foreach( $users as $user ) { // Add to email array? $email[$user['i18n']][] = $user['email']; } $i18n_languages = array_keys($email); // Get report settings from ini file $ini_file = get_all_files($_PAGE_INFO['base_path'] . SKIN_DIR . $_PAGE_INFO['skin'] . "/", array("ini")); $_PAGE_INFO['ini'] = parse_ini_file($ini_file[0], true); // Get system currencies $currencies = db_fetch_system_currencies(); if( is_array($i18n_languages) ) foreach( $i18n_languages as $i18n ) { // Set language i18n_settext_language($i18n); // type of equipment $type = db_fetch_system_devices($i18n, $row_lance['device']); // Subject for the mail switch( $msg_type ) { case 'goedkeuring vereist': // internal mail $subject = ___("Service of {1} needs approval - Workorder {0}", $wo['nummer'], $row_lance['idcode'], $type[0]['naam'], $currencies[$wo['valuta']]['symbol'], sprintf_amount($wo['valuta'], $wo['totaal_debet'] + $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_debet'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['max_bedrag'], FALSE) ); if( $wo['max_bedrag'] ) { $msg_text = ___("The repairs for {2} {1} are above {7} and need approval", $wo['nummer'], $row_lance['idcode'], $type[0]['naam'], $currencies[$wo['valuta']]['symbol'], sprintf_amount($wo['valuta'], $wo['totaal_debet'] + $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_debet'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['max_bedrag'], FALSE) ); } else { $msg_text = ___("The repairs for {2} {1} are {3} and need approval because no maximum is set", $wo['nummer'], $row_lance['idcode'], $type[0]['naam'], $currencies[$wo['valuta']]['symbol'], sprintf_amount($wo['valuta'], $wo['totaal_debet'] + $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_debet'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['max_bedrag'], FALSE) ); } $sep = "\n"; if( $wo['opmerking_int'] ) { $msg_text .= $sep . "\n" . _("Remarks (internal)") . ":\n
" . trim($wo['opmerking_int']) . "
"; $sep = ""; } if( $wo['opmerking_ext'] ) { $msg_text .= $sep . "\n" . _("Remarks (external)") . ":\n
" . trim($wo['opmerking_ext']) . "
"; $sep = ""; } // Generate price quote, but user knows best (don't generate a PDF when one is provided) if( !$file ) { require_once("include/report_workorder.php"); $file = report_workorder($wo, 'offerte', $i18n); $file['omschrijving'] = $report['filename']; } break; case 'offerte': // mail to the customer $subject = ___("Quotation for repair of {1} - Workorder {0}", $wo['nummer'], $row_lance['idcode'], $type[0]['naam'], $currencies[$wo['valuta']]['symbol'], sprintf_amount($wo['valuta'], $wo['totaal_debet'] + $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_debet'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['max_bedrag'], FALSE), $_PAGE_INFO['ini']['general']['company'] ); $msg_text = ___("Please confirm the attached quotation for {2} {1} to {8}", $wo['nummer'], $row_lance['idcode'], $type[0]['naam'], $currencies[$wo['valuta']]['symbol'], sprintf_amount($wo['valuta'], $wo['totaal_debet'] + $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_debet'], FALSE), sprintf_amount($wo['valuta'], $wo['totaal_credit'], FALSE), sprintf_amount($wo['valuta'], $wo['max_bedrag'], FALSE), $_PAGE_INFO['ini']['general']['company'] ); $sep = "\n"; if( $wo['opmerking_ext'] ) { $msg_text .= $sep . "\n" . _("Remarks") . ":\n
" . trim($wo['opmerking_ext']) . "
"; $sep = ""; } // Generate price quote, but user knows best (don't generate a PDF when one is provided) if( !$file ) { require_once("include/report_workorder.php"); $file = report_workorder($wo, 'offerte', $i18n); $file['omschrijving'] = $report['filename']; $file['zkl'] = $wo['zkl']; $file['public'] = 1; } break; default: // wrong call trigger_error("workorder status \"" . $status . "\" not implemented", E_USER_ERROR); return FALSE; } // Define font family $content = mail_default_stylesheet(); /************************************/ /* Welcome text */ /************************************/ $content .= _("Dear MTinfo user") . ",

"; /************************************/ /* Body text */ /************************************/ // (filled in above while determining the recipients's role) $content .= nl2br($msg_text); $content .= "

"; /************************************/ /* Exit text */ /************************************/ $content .= _("Best regards") . ",

"; $content .= $_PAGE_INFO['skin_name'] . "

"; $content .= $_PAGE_INFO['ini']['report']['mail'] . "
"; $content .= $_PAGE_INFO['ini']['report']['website']; if (strlen($_PAGE_INFO['ini']['report']['footer_text'])) { $content .= "

" . $_PAGE_INFO['ini']['report']['footer_text']; } if( $email[$i18n] ) { // Send mail // TO DO: "from" address must be a valid address so the recipient // can reply to the message send_mail(implode(",", array_unique($email[$i18n])), "", "", $_PAGE_INFO['ini']['mail_from']['service'], $subject, $content, $file); } } // Restore user's language i18n_settext_language($_PAGE_INFO['i18n']); // done and okay return TRUE; } /************************************************************************/ /* */ /* Action script support (recursively store system components, versions */ /* and modifications (the change log) */ /* */ /************************************************************************/ function so_update_version_changelog($version, $changelog, $changelog_documents) { // Get database identifier for the version if( is_array($version) ) $version_id = $version['id']; else if( is_numeric($version) ) $version_id = $version; else { trigger_error("Numeric version id expected", E_USER_ERROR); return FALSE; } // Existing change log items $original_changes = db_fetch_version_changelog($version_id); // Check if any of the items have been deleted if( is_array($original_changes) && is_array($changelog) ) { foreach( $original_changes as $org_change ) { $found = FALSE; foreach( $changelog as $new_change ) if( isset($new_change['id']) && substr($new_change['id'], 0, 4) != "tmp_" ) if ($new_change['id'] == $org_change['id']) $found = TRUE; // Remove? if( !$found ) db_delete_version_changelog($org_change['id']); } } // New or updated change log items if( is_array($changelog) ) { foreach( $changelog as $change ) { // save identifier (we need to keep the 'tmp' name for new items when saving the documents) $doc_index = $change['id']; if( !isset($change['id']) || substr($change['id'], 0, 4) == "tmp_" ) { // new change log item $change['id'] = db_store_version_changelog($version_id, $change); if( $change['id'] === FALSE ) return FALSE; } else { db_update_version_changelog($change); } // Save links with the equipment types db_link_version_changelog($change['id'], $change['device'], TRUE); // Update the documentation; may be NULL (or not set) when not read earlier, in which // case there are no changes in the documentation, so the documents in the database // mustn't be touched if( is_array($changelog_documents[$doc_index]) ) { db_update_files($change['id'], "changelog_versie_change_documenten", $changelog_documents[$doc_index]); } } } return TRUE; } function so_update_system_version($syscomp, $versions, $version_documents) { // Get database identifier for the system component if( is_array($syscomp) ) $syscomp_id = $syscomp['id']; else if( is_numeric($syscomp) ) $syscomp_id = $syscomp; else { trigger_error("Numeric system component id expected", E_USER_ERROR); return FALSE; } // Existing version $original_versions = db_search_system_versions($_SESSION[$_PAGE_INFO['id']]['i18n'], $syscomp_id); // Check if any of the items have been deleted if( is_array($original_versions) && is_array($versions) ) { foreach( $original_versions as $org_version ) { $found = FALSE; foreach( $versions as $new_version ) if( isset($new_version['id']) && substr($new_version['id'], 0, 4) != "tmp_" ) if ($new_version['id'] == $org_version['id']) $found = TRUE; // Remove? if( !$found ) db_delete_system_version($org_version['id']); } } if( is_array($versions) ) { foreach( $versions as $version ) { // save identifier (we need to keep the 'tmp' name for new items when saving the documents) $doc_index = $version['id']; // set the system component identifier $version['syscomp'] = $syscomp_id; if( !isset($version['id']) || substr($version['id'], 0, 4) == "tmp_" ) { // new version $version['id'] = db_store_system_version($version); if( $version['id'] === FALSE ) return FALSE; } else { db_update_system_version($version); } // Save the links with the equipment type db_link_system_version($version['id'], $version['device'], TRUE); // Update change log so_update_version_changelog($version['id'], $version['changelog'], $version['changelog_doc']); // Update the documentation; may be NULL (or not set) when not read earlier, in which // case there are no changes in the documentation, so the documents in the database // mustn't be touched if( is_array($version_documents) ) { db_update_files($version['id'], "changelog_versie_documenten", $version_documents[$doc_index]); } } } return TRUE; } /************************************************************************/ /* */ /* Generic */ /* */ /************************************************************************/ /** * Callback for 'uasort()'. Sorts an array by 'type', 'syscomp', 'version' * and 'change'. The sort order is in $_PAGE_INFO['sort_order']. * The data to sort on is expected in $_PAGE_INFO['sort_order'], which can // be a string as above, or an array with column names */ function workorder_sort_callback($a, $b) { global $_PAGE_INFO; if( !is_array($sort_items = $_PAGE_INFO['sort_order']) ) switch( $_PAGE_INFO['sort_order'] ) { case 'type': $sort_items = array('type','syscomp','version','change'); break; case 'syscomp': $sort_items = array('syscomp','version','change','type'); break; case 'version': $sort_items = array('version','change','type','syscomp'); break; case 'change': $sort_items = array('change','version','syscomp','type'); break; default: // undefined return 0; } foreach( $sort_items as $sort_item ) { $retval = strcasecmp($a[$sort_item][$_PAGE_INFO['sort'][$sort_item]], $b[$sort_item][$_PAGE_INFO['sort'][$sort_item]]); if( $retval != 0 ) return $retval; } // the same return 0; } ?>