Bestellvorschlag table for saved values and auftrag WIP

This commit is contained in:
OpenXE 2022-12-31 17:00:52 +01:00
parent aa3dea0277
commit 5b74049f5c
9 changed files with 296 additions and 230518 deletions

View File

@ -1,6 +0,0 @@
{
"host": "localhost",
"database": "openxe",
"user": "openxe",
"passwd": "openxe"
}

View File

@ -1,343 +0,0 @@
<?php
/*
* Helper to compare database structures from files vs. database
*
* Copyright (c) 2022 OpenXE project
*
*/
/*
MariaDB [openxe]> SHOW FULL db_def;
+----------------------------------------------+------------+
| Tables_in_openxe | Table_type |
+----------------------------------------------+------------+
| abrechnungsartikel | BASE TABLE |
| abrechnungsartikel_gruppe | BASE TABLE |
| abschlagsrechnung_rechnung | BASE TABLE |
| accordion | BASE TABLE |
| adapterbox | BASE TABLE |
| adapterbox_log | BASE TABLE |
| adapterbox_request_log | BASE TABLE |
| adresse | BASE TABLE |
| adresse_abosammelrechnungen | BASE TABLE |
| adresse_accounts | BASE TABLE |
| adresse_filter | BASE TABLE |
| adresse_filter_gruppen | BASE TABLE |
...
MariaDB [openxe]> SHOW FULL COLUMNS FROM wiki;
+-------------------+--------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------------------+--------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
| id | int(11) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | |
| name | varchar(255) | utf8mb3_general_ci | YES | MUL | NULL | | select,insert,update,references | |
| content | longtext | utf8mb3_general_ci | NO | | NULL | | select,insert,update,references | |
| lastcontent | longtext | utf8mb3_general_ci | NO | | NULL | | select,insert,update,references | |
| wiki_workspace_id | int(11) | NULL | NO | | 0 | | select,insert,update,references | |
| parent_id | int(11) | NULL | NO | | 0 | | select,insert,update,references | |
| language | varchar(32) | utf8mb3_general_ci | NO | | | | select,insert,update,references | |
+-------------------+--------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
MariaDB [openxe]> show keys from wiki;
+-------+------------+----------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Ignored |
+-------+------------+----------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| wiki | 0 | PRIMARY | 1 | id | A | 244 | NULL | NULL | | BTREE | | | NO |
| wiki | 0 | suche | 1 | name | A | 244 | NULL | NULL | YES | BTREE | | | NO |
| wiki | 0 | suche | 2 | wiki_workspace_id | A | 244 | NULL | NULL | | BTREE | | | NO |
| wiki | 1 | name | 1 | name | A | 244 | NULL | NULL | YES | BTREE | | | NO |
+-------+------------+----------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
*/
require('mustal_mysql_upgrade_tool.php');
$connection_info_file_name = "connection_info.json";
$target_folder = ".";
$tables_file_name_wo_folder = "db_schema.json";
$tables_file_name_w_folder = $target_folder."/".$tables_file_name_wo_folder;
$delimiter = ";";
$quote = '"';
$sql_file_name = "upgrade.sql";
$color_red = "\033[31m";
$color_green = "\033[32m";
$color_yellow = "\033[33m";
$color_default = "\033[39m";
// -------------------------------- START
echo("\n");
if ($argc > 1) {
if (in_array('-v', $argv)) {
$verbose = true;
} else {
$verbose = false;
}
if (in_array('-f', $argv)) {
$force = true;
} else {
$force = false;
}
if (in_array('-e', $argv)) {
$export = true;
} else {
$export = false;
}
if (in_array('-c', $argv)) {
$compare = true;
} else {
$compare = false;
}
if (in_array('-i', $argv)) {
$onlytables = true;
} else {
$onlytables = false;
}
if (in_array('-upgrade', $argv)) {
$upgrade = true;
} else {
$upgrade = false;
}
if (in_array('-do', $argv)) {
$doupgrade = true;
} else {
$doupgrade = false;
}
if (in_array('-clean', $argv)) {
$clean = true;
} else {
$clean = false;
}
if (in_array('-utf8fix', $argv)) {
$utf8fix = true;
} else {
$utf8fix = false;
}
$connection_info_contents = file_get_contents($connection_info_file_name);
if (!$connection_info_contents) {
echo("Unable to load $connection_info_file_name\n");
exit;
}
$connection_info = json_decode($connection_info_contents, true);
$host = $connection_info['host'];
$user = $connection_info['user'];
$passwd = $connection_info['passwd'];
$schema = $connection_info['database'];
echo("--------------- Loading from database '$schema@$host'... ---------------\n");
$db_def = mustal_load_tables_from_db($host, $schema, $user, $passwd, $mustal_replacers);
if (empty($db_def)) {
echo ("Could not load from $schema@$host\n");
exit;
}
echo("--------------- Loading from database '$schema@$host' complete. ---------------\n");
if ($export) {
echo("--------------- Export to JSON... ---------------\n");
// $result = save_tables_to_csv($db_def, $target_folder, $tables_file_name_wo_folder, $delimiter, $quote, $keys_postfix, $force);
$result = mustal_save_tables_to_json($db_def, $target_folder, $tables_file_name_wo_folder, $force);
if ($result != 0) {
$result_texts = array("ok","key postfix error","table list file error","table file error","key file error");
echo ("Could not save to JSON (".$result_texts[$result]."). To overwrite, use -f.\n");
exit;
}
echo("Exported ".count($db_def['tables'])." tables.\n");
echo("--------------- Export to JSON ($tables_file_name_w_folder) complete. ---------------\n");
}
if ($compare || $upgrade) {
// Results here as ['text'] ['diff']
$compare_differences = array();
echo("--------------- Loading from JSON... ---------------\n");
$compare_def = mustal_load_tables_from_json($target_folder, $tables_file_name_wo_folder);
if (empty($compare_def)) {
echo ("Could not load from JSON $tables_file_name_w_folder\n");
exit;
}
echo("--------------- Loading from JSON complete. ---------------\n");
// Do the comparison
/*
echo("--------------- Comparing JSON '".$compare_def['database']."@".$compare_def['host']."' vs. database '$schema@$host' ---------------\n");
echo(count($compare_def['tables'])." tables in JSON, ".count($db_def['tables'])." tables in database.\n");
$compare_differences = compare_table_array($db_def,"in DB",$compare_def,"in JSON",false);
echo("Comparison found ".(empty($compare_differences)?0:count($compare_differences))." differences.\n");
if ($verbose) {
foreach ($compare_differences as $compare_difference) {
$comma = "";
foreach ($compare_difference as $key => $value) {
echo($comma."$key => '$value'");
$comma = ", ";
}
echo("\n");
}
}*/
echo("--------------- Comparing database '$schema@$host' vs. JSON '".$compare_def['database']."@".$compare_def['host']."' ---------------\n");
if($utf8fix) {
$column_collation_aliases = array(
['utf8mb3_general_ci','utf8_general_ci']
);
} else {
$column_collation_aliases = array();
}
$compare_differences = mustal_compare_table_array($compare_def,"in JSON",$db_def,"in DB",true,$column_collation_aliases);
echo((empty($compare_differences)?0:count($compare_differences))." differences.\n");
if ($verbose) {
foreach ($compare_differences as $compare_difference) {
$comma = "";
foreach ($compare_difference as $key => $value) {
echo($comma."$key => [$value]");
$comma = ", ";
}
echo("\n");
}
}
echo("--------------- Comparison complete. ---------------\n");
}
if ($upgrade) {
// First create all db_def that are missing in the db
echo("--------------- Calculating database upgrade for '$schema@$host'... ---------------\n");
$upgrade_sql = array();
$result = mustal_calculate_db_upgrade($compare_def, $db_def, $upgrade_sql, $mustal_replacers);
if ($result != 0) {
echo("Error: $result\n");
exit;
}
if (!empty($result)) {
echo(count($result)." errors.\n");
if ($verbose) {
foreach($result as $error) {
echo("Code: ".$error[0]." '".$error[1]."'.");
}
}
return(-1);
}
echo("--------------- Database upgrade for '$schema@$host'... ---------------\n");
if ($verbose) {
foreach($upgrade_sql as $statement) {
echo($statement."\n");
}
}
echo(count($upgrade_sql)." upgrade statements\n");
echo("--------------- Database upgrade calculated for '$schema@$host' (show SQL with -v). ---------------\n");
if ($doupgrade) {
echo("--------------- Executing database upgrade for '$schema@$host' database will be written! ---------------\n");
// First get the contents of the database table structure
$mysqli = mysqli_connect($host, $user, $passwd, $schema);
/* Check if the connection succeeded */
if (!$mysqli) {
echo ("Failed to connect!\n");
} else {
$counter = 0;
$error_counter = 0;
$number_of_statements = count($upgrade_sql);
foreach ($upgrade_sql as $sql) {
$counter++;
echo("\rUpgrade step $counter of $number_of_statements... ");
if ($verbose) {
echo("(".substr($sql,0,100)."...) ");
}
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
$error = " not ok: ". mysqli_error($mysqli)."\n";
echo($error);
file_put_contents("./errors.txt",$error.$sql."\n",FILE_APPEND);
$error_counter++;
} else {
echo("ok.\r");
}
}
echo("--------------- Executing database upgrade for '$schema@$host' executed. ---------------\n");
echo("$error_counter errors.\n");
echo("--------------- Executing database upgrade for '$schema@$host' done. ---------------\n");
echo("--------------- Checking database upgrade for '$schema@$host'... ---------------\n");
$db_def = mustal_load_tables_from_db($host, $schema, $user, $passwd, $mustal_replacers);
echo("--------------- Comparing database '$schema@$host' vs. JSON '".$compare_def['database']."@".$compare_def['host']."' ---------------\n");
$compare_differences = mustal_compare_table_array($compare_def,"in JSON",$db_def,"in DB",true);
echo((empty($compare_differences)?0:count($compare_differences))." differences.\n");
}
}
} // upgrade
echo("--------------- Done. ---------------\n");
echo("\n");
} else {
info();
exit;
}
function info() {
echo("OpenXE database compare\n");
echo("Copyright 2022 (c) OpenXE project\n");
echo("\n");
echo("Export database structures in a defined format for database comparison / upgrade\n");
echo("Options:\n");
echo("\t-v: verbose output\n");
echo("\t-f: force override of existing files\n");
echo("\t-e: export database structure to files\n");
echo("\t-c: compare content of files with database structure\n");
echo("\t-i: ignore column definitions\n");
echo("\t-utf8fix: apply fix for 'utf8' != 'utf8mb3'\n");
echo("\t-upgrade: Create the needed SQL to upgrade the database to match the JSON\n");
echo("\t-do: Execute the SQL to upgrade the database to match the JSON (risky!)\n");
echo("\t-clean: (not yet implemented) Create the needed SQL to remove items from the database not in the JSON\n");
echo("\n");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,661 +0,0 @@
<?php
/*
MUSTAL Mysql Upgrade Schema Tool by Alex Ledis
Helper to compare database structures from JSON files vs. database and upgrade database
Copyright (c) 2022 Alex Ledis
Licensed under AGPL v3
Version 1.0
function mustal_load_tables_from_db(string $host, string $schema, string $user, string $passwd, $replacers) : array
Load structure from db connection to an array.
function mustal_save_tables_to_json(array $db_def, string $path, string $tables_file_name, bool $force) : int
Save structure from array to a JSON file.
function mustal_load_tables_from_json(string $path, string $tables_file_name) : array
Load structure from JSON file into array.
function mustal_compare_table_array(array $nominal, string $nominal_name, array $actual, string $actual_name, bool $check_column_definitions) : array
Compare two database structures
Returns a structured array containing information on all the differences.
function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$upgrade_sql) : int
Generate the SQL needed to upgrade the database to match the definition, based on a comparison.
Data structure in Array and JSON
{
"host": "hostname",
"database": "schemaname",
"user": "username",
"tables": [
{
"name": "",
"type": "",
"columns": [
{
"Field": "",
"Type": "",
"Collation": "",
"Null": "",
"Key": "",
"Default": "",
"Extra": "",
"Privileges": "",
"Comment": ""
}
],
"keys": [
{
"Key_name": "",
"columns": [
"",
""
]
}
]
}
]
}
*/
// These default values will not be in quotes, converted to lowercase and be replaced by the second entry
$mustal_replacers = [
['current_timestamp','current_timestamp()'],
['on update current_timestamp','on update current_timestamp()']
];
// Load all db_def from a DB connection into a db_def array
function mustal_load_tables_from_db(string $host, string $schema, string $user, string $passwd, $replacers) : array {
// First get the contents of the database table structure
$mysqli = mysqli_connect($host, $user, $passwd, $schema);
/* Check if the connection succeeded */
if (!$mysqli) {
return(array());
}
// Get db_def and views
$sql = "SHOW FULL tables";
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
return(array());
}
while ($row = mysqli_fetch_assoc($query_result)) {
$table = array();
$table['name'] = $row['Tables_in_'.$schema];
$table['type'] = $row['Table_type'];
$tables[] = $table; // Add table to list of tables
}
// Get and add columns of the table
foreach ($tables as &$table) {
$sql = "SHOW FULL COLUMNS FROM ".$table['name'];
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
return(array());
}
$columns = array();
while ($column = mysqli_fetch_assoc($query_result)) {
// Do some harmonization
if ($column['Default'] !== NULL) {
mustal_sql_replace_reserved_functions($column,$replacers);
$column['Default'] = mustal_mysql_put_text_type_in_quotes($column['Type'],$column['Default']);
}
$columns[] = $column; // Add column to list of columns
}
$table['columns'] = $columns;
$sql = "SHOW KEYS FROM ".$table['name'];
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
return(array());
}
$keys = array();
while ($key = mysqli_fetch_assoc($query_result)) {
$keys[] = $key; // Add key to list of keys
}
// Compose comparable format for keys
$composed_keys = array();
foreach ($keys as $key) {
// Check if this key exists already
$key_pos = array_search($key['Key_name'],array_column($composed_keys,'Key_name'));
if ($key_pos == false) {
// New key
$composed_key = array();
$composed_key['Key_name'] = $key['Key_name'];
$composed_key['Index_type'] = $key['Index_type'];
$composed_key['columns'][] = $key['Column_name'];
$composed_keys[] = $composed_key;
} else {
// Given key, add column
$composed_keys[$key_pos]['columns'][] .= $key['Column_name'];
}
}
unset($key);
$table['keys'] = $composed_keys;
unset($composed_keys);
}
unset($table);
$result = array();
$result['host'] = $host;
$result['database'] = $schema;
$result['user'] = $user;
$result['tables'] = $tables;
return($result);
}
function mustal_save_tables_to_json(array $db_def, string $path, string $tables_file_name, bool $force) : int {
// Prepare db_def file
if (!is_dir($path)) {
mkdir($path);
}
if (!$force && file_exists($path."/".$tables_file_name)) {
return(2);
}
$tables_file = fopen($path."/".$tables_file_name, "w");
if (empty($tables_file)) {
return(2);
}
fwrite($tables_file, json_encode($db_def,JSON_PRETTY_PRINT));
fclose($tables_file);
return(0);
}
// Load all db_def from JSON file
function mustal_load_tables_from_json(string $path, string $tables_file_name) : array {
$db_def = array();
$contents = file_get_contents($path."/".$tables_file_name);
if (!$contents) {
return(array());
}
$db_def = json_decode($contents, true);
if (!$db_def) {
return(array());
}
return($db_def);
}
// Compare two definitions
// Report based on the first array
// Return Array
// $column_collation_aliases may contain synonyms for collations e.g. utf8mb3_general_ci vs utf8_general_ci
function mustal_compare_table_array(array $nominal, string $nominal_name, array $actual, string $actual_name, bool $check_column_definitions, array $column_collation_aliases = array()) : array {
$compare_differences = array();
if (count($nominal['tables']) != count($actual['tables'])) {
$compare_difference = array();
$compare_difference['type'] = "Table count";
$compare_difference[$nominal_name] = count($nominal['tables']);
$compare_difference[$actual_name] = count($actual['tables']);
$compare_differences[] = $compare_difference;
}
foreach ($nominal['tables'] as $database_table) {
$found_table = array();
foreach ($actual['tables'] as $compare_table) {
if ($database_table['name'] == $compare_table['name']) {
$found_table = $compare_table;
break;
}
}
unset($compare_table);
if ($found_table) {
// Check type table vs view
if ($database_table['type'] != $found_table['type']) {
$compare_difference = array();
$compare_difference['type'] = "Table type";
$compare_difference['table'] = $database_table['name'];
$compare_difference[$nominal_name] = $database_table['type'];
$compare_difference[$actual_name] = $found_table['type'];
$compare_differences[] = $compare_difference;
}
// Only BASE TABLE supported now
if ($found_table['type'] != 'BASE TABLE') {
continue;
}
// Check columns
$compare_table_columns = array_column($found_table['columns'],'Field');
foreach ($database_table['columns'] as $column) {
$column_name_to_find = $column['Field'];
$column_key = array_search($column_name_to_find,$compare_table_columns,true);
if ($column_key !== false) {
// Compare the properties of the columns
if ($check_column_definitions) {
$found_column = $found_table['columns'][$column_key];
foreach ($column as $key => $value) {
// Apply aliases
if (!empty($column_collation_aliases)) {
foreach($column_collation_aliases as $column_collation_alias) {
if ($value == $column_collation_alias[0]) {
$value = $column_collation_alias[1];
}
if ($found_column[$key] == $column_collation_alias[0]) {
$found_column[$key] = $column_collation_alias[1];
}
}
}
if ($found_column[$key] != $value) {
if ($key != 'Key') { // Keys will be handled separately
$compare_difference = array();
$compare_difference['type'] = "Column definition";
$compare_difference['table'] = $database_table['name'];
$compare_difference['column'] = $column['Field'];
$compare_difference['property'] = $key;
$compare_difference[$nominal_name] = $value;
$compare_difference[$actual_name] = $found_column[$key];
$compare_differences[] = $compare_difference;
}
}
}
unset($value);
} // $check_column_definitions
} else {
$compare_difference = array();
$compare_difference['type'] = "Column existence";
$compare_difference['table'] = $database_table['name'];
$compare_difference[$nominal_name] = $column['Field'];
$compare_differences[] = $compare_difference;
}
}
unset($column);
// Check keys
$compare_table_sql_indexs = array_column($found_table['keys'],'Key_name');
foreach ($database_table['keys'] as $sql_index) {
$sql_index_name_to_find = $sql_index['Key_name'];
$sql_index_key = array_search($sql_index_name_to_find,$compare_table_sql_indexs,true);
if ($sql_index_key !== false) {
// Compare the properties of the sql_indexs
if ($check_column_definitions) {
$found_sql_index = $found_table['keys'][$sql_index_key];
foreach ($sql_index as $key => $value) {
if ($found_sql_index[$key] != $value) {
// if ($key != 'permissions') {
$compare_difference = array();
$compare_difference['type'] = "Key definition";
$compare_difference['table'] = $database_table['name'];
$compare_difference['key'] = $sql_index['Key_name'];
$compare_difference['property'] = $key;
$compare_difference[$nominal_name] = implode(',',$value);
$compare_difference[$actual_name] = implode(',',$found_sql_index[$key]);
$compare_differences[] = $compare_difference;
// }
}
}
unset($value);
} // $check_sql_index_definitions
} else {
$compare_difference = array();
$compare_difference['type'] = "Key existence";
$compare_difference['table'] = $database_table['name'];
$compare_difference[$nominal_name] = $sql_index['Key_name'];
$compare_differences[] = $compare_difference;
}
}
unset($sql_index);
} else {
$compare_difference = array();
$compare_difference['type'] = "Table existence";
$compare_difference[$nominal_name] = $database_table['name'];
$compare_differences[] = $compare_difference;
}
}
unset($database_table);
return($compare_differences);
}
// Generate SQL to create or modify column
function mustal_column_sql_definition(string $table_name, array $column, array $reserved_words_without_quote) : string {
foreach($column as $key => &$value) {
$value = (string) $value;
$value = mustal_column_sql_create_property_definition($key,$value,$reserved_words_without_quote);
}
// Default handling here
if ($column['Default'] == " DEFAULT ''") {
$column['Default'] = "";
}
$sql =
$column['Type'].
$column['Null'].
$column['Default'].
$column['Extra'].
$column['Collation'];
return($sql);
}
// Generate SQL to modify a single column property
function mustal_column_sql_create_property_definition(string $property, string $property_value, array $reserved_words_without_quote) : string {
switch ($property) {
case 'Type':
break;
case 'Null':
if ($property_value == "NO") {
$property_value = " NOT NULL"; // Idiotic...
}
if ($property_value == "YES") {
$property_value = " NULL"; // Also Idiotic...
}
break;
case 'Default':
// Check for MYSQL function mustal_call as default
if (in_array(strtolower($property_value),$reserved_words_without_quote)) {
$quote = "";
} else {
// Remove quotes if there are
$property_value = trim($property_value,"'");
$quote = "'";
}
$property_value = " DEFAULT $quote".$property_value."$quote";
break;
case 'Extra':
if ($property_value != '') {
$property_value = " ".$property_value;
}
break;
case 'Collation':
if ($property_value != '') {
$property_value = " COLLATE ".$property_value;
}
break;
default:
$property_value = "";
break;
}
return($property_value);
}
// Replaces different variants of the same function mustal_to allow comparison
function mustal_sql_replace_reserved_functions(array &$column, array $replacers) {
$result = strtolower($column['Default']);
foreach ($replacers as $replace) {
if ($result == $replace[0]) {
$result = $replace[1];
}
}
$column['Default'] = $result;
$result = strtolower($column['Extra']);
foreach ($replacers as $replace) {
if ($result == $replace[0]) {
$result = $replace[1];
}
}
$column['Extra'] = $result;
}
// Is it a text type? -> Use quotes then
function mustal_mysql_put_text_type_in_quotes(string $checktype, string $value) : string {
$types = array('char','varchar','tinytext','text','mediumtext','longtext');
foreach($types as $type) {
if (stripos($checktype, $type) !== false) {
return("'".$value."'");
}
}
return($value);
}
function mustal_implode_with_quote(string $quote, string $delimiter, array $array_to_implode) : string {
return($quote.implode($quote.$delimiter.$quote, $array_to_implode).$quote);
}
// Calculate the sql neccessary to update the database
// returns array(code,text)
// Error codes:
// 0 ok
// 1 Upgrade type of table not supported
// 2 Error on table upgrade
// 3 Error on column existence upgrade
// 4 Error on column existence upgrade
// 5 Error on column definition upgrade
// 6 Error on column definition upgrade
// 7 Error on key existence upgrade
// 8 Error on key existence upgrade
// 9 Error on key definition upgrade
// 10 Error on key definition upgrade
// 11 Table type upgrade not supported
// 12 Upgrade type not supported
function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$upgrade_sql, array $replacers) : array {
$result = array();
$upgrade_sql = array();
$compare_differences = mustal_compare_table_array($compare_def,"in JSON",$db_def,"in DB",true);
if (count($compare_differences) > 0) {
$upgrade_sql[] = ("SET SQL_MODE='ALLOW_INVALID_DATES';");
$upgrade_sql[] = ("SET SESSION innodb_strict_mode=OFF;");
}
foreach ($compare_differences as $compare_difference) {
switch ($compare_difference['type']) {
case 'Table existence':
// Get table definition from JSON
$table_name = $compare_difference['in JSON'];
$table_key = array_search($table_name,array_column($compare_def['tables'],'name'));
if ($table_key !== false) {
$table = $compare_def['tables'][$table_key];
switch ($table['type']) {
case 'BASE TABLE':
// Create table in DB
$sql = "";
$sql = "CREATE TABLE `".$table['name']."` (";
$comma = "";
foreach ($table['columns'] as $column) {
$sql .= $comma."`".$column['Field']."` ".mustal_column_sql_definition($table_name, $column,array_column($replacers,1));
$comma = ", ";
}
// Add keys
$comma = ", ";
foreach ($table['keys'] as $key) {
if ($key['Key_name'] == 'PRIMARY') {
$keystring = "PRIMARY KEY ";
} else {
if(array_key_exists('Index_type', $key)) {
$index_type = $key['Index_type'];
} else {
$index_type = "";
}
$keystring = $index_type." KEY `".$key['Key_name']."` ";
}
$sql .= $comma.$keystring."(`".implode("`,`",$key['columns'])."`) ";
}
$sql .= ")";
$upgrade_sql[] = $sql;
break;
default:
$result[] = array(1,"Upgrade type '".$table['type']."' on table '".$table['name']."' not supported.");
break;
}
} else {
$result[] = array(2,"Error table_key while creating upgrade for table existence `$table_name`.");
}
break;
case 'Column existence':
$table_name = $compare_difference['table'];
$column_name = $compare_difference['in JSON'];
$table_key = array_search($table_name,array_column($compare_def['tables'],'name'));
if ($table_key !== false) {
$table = $compare_def['tables'][$table_key];
$columns = $table['columns'];
$column_key = array_search($column_name,array_column($columns,'Field'));
if ($column_key !== false) {
$column = $table['columns'][$column_key];
$sql = "ALTER TABLE `$table_name` ADD COLUMN `".$column_name."` ";
$sql .= mustal_column_sql_definition($table_name, $column, array_column($replacers,1));
$sql .= ";";
$upgrade_sql[] = $sql;
}
else {
$result[] = array(3,"Error column_key while creating column '$column_name' in table '".$table['name']."'.");
}
}
else {
$result[] = array(4,"Error table_key while creating upgrade for column existence '$column_name' in table '$table_name'.");
}
// Add Column in DB
break;
case 'Column definition':
$table_name = $compare_difference['table'];
$column_name = $compare_difference['column'];
$table_key = array_search($table_name,array_column($compare_def['tables'],'name'));
if ($table_key !== false) {
$table = $compare_def['tables'][$table_key];
$columns = $table['columns'];
$column_names = array_column($columns,'Field');
$column_key = array_search($column_name,$column_names);
if ($column_key !== false) {
$column = $table['columns'][$column_key];
$sql = "ALTER TABLE `$table_name` MODIFY COLUMN `".$column_name."` ";
$sql .= mustal_column_sql_definition($table_name, $column,array_column($replacers,1));
$sql .= ";";
$upgrade_sql[] = $sql;
}
else {
$result[] = array(5,"Error column_key while modifying column '$column_name' in table '".$table['name']."'.");
}
}
else {
$result[] = array(6,"Error table_key while modifying column '$column_name' in table '$table_name'.");
return(6);
}
// Modify Column in DB
break;
case 'Key existence':
$table_name = $compare_difference['table'];
$key_name = $compare_difference['in JSON'];
$table_key = array_search($table_name,array_column($compare_def['tables'],'name'));
if ($table_key !== false) {
$table = $compare_def['tables'][$table_key];
$keys = $table['keys'];
$key_names = array_column($keys,'Key_name');
$key_key = array_search($key_name,$key_names);
if ($key_key !== false) {
$key = $table['keys'][$key_key];
$sql = "ALTER TABLE `$table_name` ADD KEY `".$key_name."` ";
$sql .= "(`".implode("`,`",$key['columns'])."`)";
$sql .= ";";
$upgrade_sql[] = $sql;
}
else {
$result[] = array(7,"Error key_key while adding key '$key_name' in table '".$table['name']."'.");
}
}
else {
$result[] = array(8,"Error table_key while adding key '$key_name' in table '$table_name'.");
}
break;
case "Key definition":
$table_name = $compare_difference['table'];
$key_name = $compare_difference['key'];
$table_key = array_search($table_name,array_column($compare_def['tables'],'name'));
if ($table_key !== false) {
$table = $compare_def['tables'][$table_key];
$keys = $table['keys'];
$key_names = array_column($keys,'Key_name');
$key_key = array_search($key_name,$key_names);
if ($key_key !== false) {
$key = $table['keys'][$key_key];
$sql = "ALTER TABLE `$table_name` DROP KEY `".$key_name."`;";
$upgrade_sql[] = $sql;
$sql = "ALTER TABLE `$table_name` ADD KEY `".$key_name."` ";
$sql .= "(`".implode("`,`",$key['columns'])."`)";
$sql .= ";";
$upgrade_sql[] = $sql;
}
else {
$result[] = array(9, "Error key_key while changing key '$key_name' in table '".$table['name']."'.");
}
}
else {
$result[] = array(10,"Error table_key while changing key '$key_name' in table '$table_name'.");
}
break;
case 'Table count':
// Nothing to do
break;
case 'Table type':
$result[] = array(11,"Upgrade type '".$compare_difference['type']."' on table '".$compare_difference['table']."' not supported.");
break;
default:
$result[] = array(12,"Upgrade type '".$compare_difference['type']."' not supported.");
break;
}
}
$upgrade_sql = array_unique($upgrade_sql);
return($result);
}

View File

@ -28444,6 +28444,55 @@
}
]
},
{
"name": "bestellvorschlag",
"type": "BASE TABLE",
"columns": [
{
"Field": "user",
"Type": "int(11)",
"Collation": null,
"Null": "NO",
"Key": "PRI",
"Default": null,
"Extra": "",
"Privileges": "select,insert,update,references",
"Comment": ""
},
{
"Field": "artikel",
"Type": "int(11)",
"Collation": null,
"Null": "NO",
"Key": "PRI",
"Default": null,
"Extra": "",
"Privileges": "select,insert,update,references",
"Comment": ""
},
{
"Field": "menge",
"Type": "int(11)",
"Collation": null,
"Null": "NO",
"Key": "",
"Default": null,
"Extra": "",
"Privileges": "select,insert,update,references",
"Comment": ""
}
],
"keys": [
{
"Key_name": "PRIMARY",
"Index_type": "BTREE",
"columns": [
"artikel",
"user"
]
}
]
},
{
"name": "bestellvorschlag_app",
"type": "BASE TABLE",

View File

@ -127,10 +127,9 @@ function mustal_load_tables_from_db(string $host, string $schema, string $user,
foreach ($keys as $key) {
// Check if this key exists already
$key_pos = array_search($key['Key_name'],array_column($composed_keys,'Key_name'));
if ($key_pos == false) {
if ($key_pos === false) {
// New key
$composed_key = array();
$composed_key['Key_name'] = $key['Key_name'];

View File

@ -15,9 +15,9 @@ class Bestellvorschlag {
$this->app->ActionHandlerInit($this);
$this->app->ActionHandler("list", "bestellvorschlag_list");
$this->app->ActionHandler("create", "bestellvorschlag_edit"); // This automatically adds a "New" button
$this->app->ActionHandler("edit", "bestellvorschlag_edit");
$this->app->ActionHandler("delete", "bestellvorschlag_delete");
// $this->app->ActionHandler("create", "bestellvorschlag_edit"); // This automatically adds a "New" button
// $this->app->ActionHandler("edit", "bestellvorschlag_edit");
// $this->app->ActionHandler("delete", "bestellvorschlag_delete");
$this->app->DefaultActionHandler("list");
$this->app->ActionHandlerListen($app);
}
@ -30,20 +30,24 @@ class Bestellvorschlag {
switch ($name) {
case "bestellvorschlag_list":
$allowed['bestellvorschlag_list'] = array('list');
$heading = array('', '', 'Nr.', 'Artikel','Lieferant','Mindestlager','Lager','Bestellt','Vorschlag','Eingabe','');
$width = array('1%','1%','1%', '20%', '10%', '1%', '1%', '1%', '1%', '5%', '1%');
$monate_absatz = $app->Secure->GetPOST('monate_absatz');
$monate_voraus = $app->Secure->GetPOST('monate_voraus');
$heading = array('', '', 'Nr.', 'Artikel','Lieferant','Mindestlager','Lager','Bestellt','Auftrag','Vorschlag','Eingabe','');
$width = array('1%','1%','1%', '20%', '10%', '1%', '1%', '1%', '1%', '1%', '1%', '1%');
// columns that are aligned right (numbers etc)
// $alignright = array(4,5,6,7,8);
$findcols = array('a.id','a.id','a.nummer','a.name_de','l.name','mindestlager','lager','bestellt','vorschlag');
$findcols = array('a.id','a.id','a.nummer','a.name_de','l.name','mindestlager','lager','bestellt','auftrag','vorschlag');
$searchsql = array('a.name_de');
$defaultorder = 1;
$defaultorderdesc = 0;
$numbercols = array(6,7,8,9);
$numbercols = array(6,7,8,9,10);
// $sumcol = array(6);
$alignright = array(6,7,8,9);
$alignright = array(6,7,8,9,10);
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',a.id,'\" />') AS `auswahl`";
@ -54,39 +58,142 @@ class Bestellvorschlag {
' name=\"menge_',
a.id,
'\" value=\"',
(SELECT mengen.vorschlag),
'\" style=\"text-align:right\">',
ROUND((SELECT mengen.vorschlag)),
'\" style=\"text-align:right; width:100%\">',
'</input>'
)";
$sql_artikel_mengen = "
SELECT
a.id,
(
SELECT
COALESCE(SUM(menge),0)
FROM
lager_platz_inhalt lpi
INNER JOIN lager_platz lp ON
lp.id = lpi.lager_platz
WHERE
lpi.artikel = a.id AND lp.sperrlager = 0
) AS lager_ber,
(
SELECT
COALESCE(SUM(menge-geliefert))
FROM
bestellung_position bp INNER JOIN bestellung b ON bp.bestellung = b.id
WHERE bp.artikel = a.id AND b.status IN ('versendet','freigegeben')
) AS bestellt_ber,
a.mindestlager - (SELECT lager_ber) - COALESCE((SELECT bestellt_ber),0) as vorschlag_ber,
FORMAT (a.mindestlager,0,'de_DE') as mindestlager,
FORMAT((SELECT lager_ber),0,'de_DE') as lager,
FORMAT(COALESCE((SELECT bestellt_ber),0),0,'de_DE') as bestellt,
if ((SELECT vorschlag_ber) > 0,FORMAT((SELECT vorschlag_ber),'0','de_DE'),0) as vorschlag
FROM
artikel a
";
$user = $app->User->GetID();
$sql_artikel_mengen = "
SELECT
a.id,
(
SELECT
COALESCE(SUM(menge),
0)
FROM
lager_platz_inhalt lpi
INNER JOIN lager_platz lp ON
lp.id = lpi.lager_platz
WHERE
lpi.artikel = a.id AND lp.sperrlager = 0
) AS lager,
(
SELECT
COALESCE(SUM(menge - geliefert))
FROM
bestellung_position bp
INNER JOIN bestellung b ON
bp.bestellung = b.id
WHERE
bp.artikel = a.id AND b.status IN(
'versendet',
'freigegeben',
'angelegt'
)
) AS bestellt,
(
SELECT
COALESCE(SUM(menge - geliefert))
FROM
auftrag_position aufp
INNER JOIN auftrag auf ON
aufp.auftrag = auf.id
WHERE
aufp.artikel = a.id AND auf.status IN(
'versendet',
'freigegeben',
'angelegt'
)
) AS auftrag,
(
SELECT
menge
FROM
bestellvorschlag bv
WHERE
bv.artikel = a.id AND bv.user = '$user'
) AS vorschlag_save,
a.mindestlager -(
SELECT
lager
) - COALESCE((
SELECT
bestellt
),
0)
+ COALESCE((
SELECT
auftrag
),
0) AS vorschlag_ber_raw,
IF(
(
SELECT
vorschlag_ber_raw
) > 0,
(
SELECT
vorschlag_ber_raw
),
0
) AS vorschlag_ber,
COALESCE(
(
SELECT
vorschlag_save
),
(
SELECT
vorschlag_ber
)
) AS vorschlag,
FORMAT(a.mindestlager, 0, 'de_DE') AS mindestlager_form,
FORMAT((
SELECT
lager
),
0,
'de_DE') AS lager_form,
FORMAT(
COALESCE((
SELECT
bestellt
),
0),
0,
'de_DE'
) AS bestellt_form,
FORMAT(
COALESCE((
SELECT
auftrag
),
0),
0,
'de_DE'
) AS auftrag_form,
FORMAT(
(
SELECT
vorschlag_ber
),
'0',
'de_DE'
) AS vorschlag_ber_form
,
FORMAT(
(
SELECT
vorschlag
),
'0',
'de_DE'
) AS vorschlag_form
FROM
artikel a
";
$sql = "SELECT SQL_CALC_FOUND_ROWS
a.id,
@ -94,11 +201,12 @@ class Bestellvorschlag {
a.nummer,
a.name_de,
l.name,
mengen.mindestlager,
mengen.lager,
mengen.bestellt,
mengen.vorschlag,"
.$input_for_menge
mengen.mindestlager_form,
mengen.lager_form,
mengen.bestellt_form,
mengen.auftrag_form,
mengen.vorschlag_ber_form,"
.$input_for_menge
."FROM
artikel a
INNER JOIN
@ -125,6 +233,31 @@ class Bestellvorschlag {
function bestellvorschlag_list() {
$submit = $this->app->Secure->GetPOST('submit');
$user = $this->app->User->GetID();
switch ($submit) {
case 'loeschen':
$sql = "DELETE FROM bestellvorschlag where user = $user";
$this->app->DB->Delete($sql);
break;
case 'speichern':
$menge_input = $this->app->Secure->GetPOSTArray();
$mengen = array();
foreach ($menge_input as $key => $menge) {
if ((strpos($key,'menge_') === 0) && ($menge !== '')) {
$artikel = substr($key,'6');
if ($menge > 0) {
$sql = "INSERT INTO bestellvorschlag (artikel, user, menge) VALUES($artikel,$user,$menge) ON DUPLICATE KEY UPDATE menge = $menge";
$this->app->DB->Insert($sql);
}
}
}
break;
}
$this->app->erp->MenuEintrag("index.php?module=bestellvorschlag&action=list", "&Uuml;bersicht");
$this->app->erp->MenuEintrag("index.php?module=bestellvorschlag&action=create", "Neu anlegen");

View File

@ -1,17 +1,70 @@
<div id="tabs-1">
[MESSAGE]
<form>
[TAB1]
<fieldset>
<table>
<legend>Stapelverarbeitung</legend>
<tr>
<td><input type="checkbox" value="1" id="autoalle" />&nbsp;alle markieren&nbsp;</td>
<td><input type="submit" class="btnBlue" name="ausfuehren" value="{|Bestellung erzeugen|}"/></td>
</tr>
</table>
</fieldset>
</form>
[MESSAGE]
<form action="" method="post">
<div class="row">
<div class="row-height">
<div class="col-xs-14 col-md-4 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<!---
<table width="100%" border="0" class="mkTableFormular">
<legend>{|Einstellungen|}</legend>
<td>{|Absatz der letzten Monate|}:</td>
<td><input type="number" min="0" name="monate_absatz" id="monate_absatz" value="[MONATE_ABSATZ]" size="20""></td>
</tr>
<tr>
<td>{|Vorausplanen Monate|}:</td>
<td><input type="number" min="0" name="monate_voraus" id="monate_voraus" value="[MONATE_VORAUS]" size="20""></td>
</tr>
</table>
--!>
</fieldset>
</div>
</div>
<div class="col-xs-14 col-md-8 col-md-height">
<div class="inside inside-full-height">
</div>
</div>
<div class="col-xs-14 col-md-2 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<table>
<legend>Aktionen</legend>
<tr>
<td><button name="submit" class="ui-button-icon" style="width:100%;" value="loeschen">{|Zur&uuml;cksetzen|}</button></td>
</tr>
<tr>
<td><button name="submit" class="ui-button-icon" style="width:100%;" value="speichern">{|Speichern|}</button></td>
</tr>
<tr>
<td><button name"submit" class="ui-button-icon" style="width:100%;" value="bestellungen_erzeugen">{|Bestellungen erzeugen|}</button></td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
<div class="row">
<div class="row-height">
<div class="col-xs-14 col-md-6 col-md-height">
<div class="inside inside-full-height">
[TAB1]
<fieldset>
<table>
<tr>
<td>
<input type="checkbox" value="1" id="autoalle" />&nbsp;alle markieren&nbsp;
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</form>
[TAB1NEXT]
</div>
@ -24,3 +77,7 @@
});
</script>