*restructured DB driver a bit
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 17 Nov 2008 16:57:52 +0000 (16:57 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 17 Nov 2008 16:57:52 +0000 (16:57 +0000)
*added shipping to DB
*added shipping to docu (not implemented yet)

git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@188 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

doc/prog_protocol.html
www/admin.php
www/inc/db/db.php
www/inc/db/db_mysql.php
www/inc/db/db_scheme.php

index e6c8803..3af00be 100644 (file)
@@ -456,6 +456,7 @@ The order XML representation looks as follows:
     totalprice="amountInCent" paid="amountInCent" status="orderstate">
   &lt;Ticket event="eventid" id="ticketid" price="priceInCent" status="ticketstate" />
   &lt;Voucher id="voucherid" price="priceInCent" value="remainingValueInCent" />
+  &lt;Shipping price="priceInCent" type="shippingtypeID">Shipping Comment&lt;/Shipping>
   &lt;DeliveryAddress>deliver address&lt;/DeliveryAddress>
   &lt;Comment>comment...&lt;/Comment>
 &lt;/Order>
@@ -463,7 +464,6 @@ The order XML representation looks as follows:
 
 <table frame="1" border="1">
 <tr><td><b>Item</b></td><td><b>Description</b></td><td><b>Occurrence</b></td></tr>
-
 <tr/>
 <tr><td>Order</td><td>Container for one single order or sale</td><td>1</td></tr>
 <tr><td>&nbsp; id</td><td>ID of the order, if already known.</td><td>0-1</td></tr>
@@ -474,9 +474,25 @@ The order XML representation looks as follows:
 <tr><td>&nbsp; totalprice</td><td>Total accumulated price of the order. Automatically filled in.</td><td>0-1</td></tr>
 <tr><td>&nbsp; paid</td><td>Amount that has already been paid. Automatically filled in.</td><td>0-1</td></tr>
 <tr><td>&nbsp; status</td><td>Current status of the order. Automatically filled in. See table below.</td><td>0-1</td></tr>
-
 <tr/>
 <tr><td>Ticket(*)</td><td>data about a single ticket bought in this order</td><td>0-unlimited</td></tr>
+<tr><td>&nbsp; id</td><td>ID of the ticket</td><td>1</td></tr>
+<tr><td>&nbsp; event</td><td>ID of the event this ticket refers to.</td><td>1</td></tr>
+<tr><td>&nbsp; price</td><td>Price of the ticket</td><td>1</td></tr>
+<tr><td>&nbsp; status</td><td>Status of the ticket (see below)</td><td>1</td></tr>
+<tr/>
+<tr><td>Voucher(*)</td><td>data about a single voucher bought in this order, vouchers that are used to pay for an order are not stored</td><td>0-unlimited</td></tr>
+<tr><td>&nbsp; id</td><td>ID of the voucher</td><td>1</td></tr>
+<tr><td>&nbsp; price</td><td>Price of the voucher (adds to price of the order)</td><td>1</td></tr>
+<tr><td>&nbsp; value</td><td>Value (in cent) of the voucher (does not add to the order, but refers to how much the voucher is worth)</td><td>1</td></tr>
+<tr/>
+<tr><td>Shipping</td><td>information about the kind of shipping used and how much it costs; if text is used it is a copy of the text from the shipping table information - it cannot be changed here</td><td>0-1</td></tr>
+<tr><td>&nbsp; price</td><td>Price of the shipping option</td><td>1</td></tr>
+<tr><td>&nbsp; type</td><td>shipping type ID</td><td>1</td></tr>
+<tr/>
+<tr><td>DeliveryAddress</td><td>the address to send the stuff to, if not present or empty the address of the customer is used</td><td>0-1</td></tr>
+<tr/>
+<tr><td>Comment</td><td>comment entered into the order by customer or seller</td><td>0-1</td></tr>
 </table>
 (*)At least one of Ticket or Voucher must be used.<p>
 
@@ -517,8 +533,9 @@ The request is an order object without most fields filled in, the response is a
 <tr><td>Order</td><td>customer</td><td>id(1), customer, seller(3), ordertime(1,4), totalprice(5), paid(1), status(6), senttime(2,4)</td></tr>
 <tr><td>Ticket</td><td>event, price(7)</td><td>event, id(1), price, status(6)</td></tr>
 <tr><td>Voucher</td><td>value, price(7)</td><td>value, price, id(1)</td></tr>
-<tr><td>DeliveryAddress</td><td>-</td><td>-</td></tr>
-<tr><td>Comment</td><td>-</td><td>-</td></tr>
+<tr><td>Shipping</td><td>type(8), price(9)</td><td>type(10), price, [text](10)</td></tr>
+<tr><td>DeliveryAddress</td><td>[text]</td><td>[text]</td></tr>
+<tr><td>Comment</td><td>[text]</td><td>[text]</td></tr>
 </table>
 (1)field is optional for checks and has no meaning there, it is recommended the server returns a dummy ID for checks<br/>
 (2)the field only exists for sales<br/>
@@ -526,7 +543,10 @@ The request is an order object without most fields filled in, the response is a
 (4)time stamps are automatically filled in with the current server time<br/>
 (5)the total price is the accumulated price of all tickets and vouchers in the order<br/>
 (6)the status fields have special meanings for checks, see below<br/>
-(7)the price field will only be honoured in the request, if the user also has the privilege to use the changeticketprice transaction<p>
+(7)the price field will only be honoured in the request, if the user also has the privilege to use the changeticketprice transaction<br/>
+(8)the shipping types that are allowed depend on whether the user has the _anyshipping privilege<br/>
+(9)price is optional, if set it is ignored if the user does not have the _repriceshipping privilege<br/>
+(10)the type in the response may be -1 if an error occurred in this case the text contains the error message, otherwise it contains a copy of the shipping option text<p>
 
 Order status for checks:
 <table frame="1" border="1">
@@ -594,6 +614,51 @@ The <tt>setordercomment</tt> transaction is used to change the orders comment. T
 
 The response body is empty or optionally contains an error message.
 
+<h3>Changing the shipping option on an order</h3>
+
+The <tt>orderchangeshipping</tt> transaction can be used to change the shipping information on an order. The request looks like:
+
+<pre>
+&lt;OrderChangeShipping orderid="orderId" type="newShippingType" price="newPriceInCent"/>
+</pre>
+
+If <tt>type</tt> is not present, the price is taken from the new shipping type. If <tt>type</tt> is not present, it is not changed. If <tt>type</tt> is empty it is reset to none (NULL) in the Database. If a price other than 0 is used, the type in the database must be present (!= NULL).<p>
+
+The response contains the updated order object or just an error message.
+
+<h3>Creating/Changing Shipping Options</h3>
+
+The <tt>setshipping</tt> creates or changes a shipping option. The request looks like:
+
+<pre>
+&lt;ShippingOption id="shippingOptionID" price="priceInCent" web="0|1" anyUser="0|1">
+  Text that describes the option
+&lt;/ShippingOption>
+</pre>
+
+If the <tt>id</tt> attribute is missing the server creates a new option. Otherwise it changes an existing one. The <tt>web</tt> attribute tells whether the option is available to customers using the web interface. The <tt>anyUser</tt> attribute tells whether the option can be used by anyone who can create an order/sale (=1) or only by users with the "_anyshipping" privilege (=0).<p>
+
+The response is empty or contains an error message.
+
+<h3>Listing Shipping Options</h3>
+
+The <tt>getshipping</tt> transaction can be used to return all shipping options. If the user has the "setshipping" or "_anyshipping" privilege the list will also contain privileged options. The request is empty. The response looks like:
+
+<pre>
+&lt;ShippingList>
+  &lt;ShippingOption id="shippingOptionID" price="priceInCent" web="0|1" anyUser="0|1">
+    Text that describes the option
+  &lt;/ShippingOption>
+  ...
+  ...
+&lt;/ShippingList>
+</pre>
+
+<h3>Adding Tickets or Vouchers to an Order</h3>
+
+tbd.
+
+
 <!-- ************************************************************************************
      ************************************************************************************
      ************************************************************************************ -->
index b7b9dac..b4f2422 100644 (file)
@@ -25,21 +25,37 @@ if(isset($_GET["CreateDB"])){
 ?>
 
 <?
-if($db->canUseDb()){
+$canUseDb=$db->canUseDb();
+if($canUseDb){
 ?>
-Database exists and is usable.
+Database exists and is usable.<p>
+
+<form action="admin.php" method="GET">
+<input type="submit" value="Show SQL Script to create DB." name="ShowCreateDB"/>
+</form>
+
 <?
 }else{
 ?>
 Database is not usable. Create?<br>
 <form action="admin.php" method="GET">
 <input type="submit" value="Yes, Create DB now." name="CreateDB"/>
+<input type="submit" value="Show SQL Script to create DB." name="ShowCreateDB"/>
 </form>
 <?
-       exit();
 }
 ?>
 
+<?
+if(isset($_GET["ShowCreateDB"])){
+       print("Creating Database...<p>");
+       $db->showCreateDb();
+}
+
+//the stuff below does not work if DB unusable
+if(!$canUseDb)
+       exit();
+?>
 
 <h2>Checking for Admin Users</h2>
 
index 2b3edd5..8e7cfc4 100644 (file)
@@ -36,30 +36,34 @@ abstract class DbEngine
        }
        
        /**returns the version of the DB layout that is required by this version of Magic Smoke*/
-       public function needVersion(){return "00.01";}
+       public function needVersion()
+       {
+               global $dbScheme;
+               return $dbScheme->version();
+       }
        
        /**returns whether the table exists; must be implemented by driver*/
        public abstract function haveTable($tablename);
        
-       /**begins a transaction; must be implemented by driver*/
+       /**begins a transaction; must be implemented by driver; use sqlBeginTransaction to create the SQL statement!*/
        public abstract function beginTransaction();
        
-       /**ends a transaction successfully; must be implemented by driver; returns true on success*/
+       /**ends a transaction successfully; must be implemented by driver; returns true on success; use sqlCommitTransaction to create the SQL statement!*/
        public abstract function commitTransaction();
        
-       /**ends a transaction with a rollback; must be implemented by driver; returns true on success*/
+       /**ends a transaction with a rollback; must be implemented by driver; returns true on success; use sqlRollbackTransaction to create the SQL statement!*/
        public abstract function rollbackTransaction();
        
-       /**gets some data from the database; $table is the name of the table, $cols is the list of columns to return or "*" for all, $where is the where clause of the SQL-statement, $orderby may contain additional ORDER BY or GROUP BY clauses; returns array of rows, which are in *_fetch_array format; returns false on error*/
+       /**gets some data from the database; $table is the name of the table, $cols is the list of columns to return or "*" for all, $where is the where clause of the SQL-statement, $orderby may contain additional ORDER BY or GROUP BY clauses; returns array of rows, which are in *_fetch_array format; returns false on error; use sqlSelect to create the SQL statement!*/
        public abstract function select($table,$cols,$where,$orderby="");
        
-       /**insert values into a table; returns false on failure, the new primary key if a sequence was set, true otherwise*/
+       /**insert values into a table; returns false on failure, the new primary key if a sequence was set, true otherwise; use sqlInsert to create the SQL statement!*/
        public abstract function insert($table,array $values);
        
-       /**update database values; returns how many rows have been changed or false for failure*/
+       /**update database values; returns how many rows have been changed or false for failure; use sqlUpdate to create the SQL statement!*/
        public abstract function update($table,array $values,$where);
        
-       /**delete database values; returns the amount of rows deleted or false if an error occurred*/
+       /**delete database values; returns the amount of rows deleted or false if an error occurred; use sqlDelete to create the SQL statement!*/
        public abstract function deleteRows($table,$where);
        
        /**creates a table; the argument is an array of the form "col-name" => array("col-type", "flags"...); use sqlCreateTable() etc. to create the actual statement*/
@@ -69,11 +73,12 @@ abstract class DbEngine
        protected function tableName($tname){return $tname;}
        
        /**returns the correct type name for the required abstract data type;
-       types that must be understood are: int32 (INTEGER), int64 (LONG INTEGER), seq32 (auto-incrementing int), seq64, string:$length (text up to 255 chars, length is optional, default is 255; VARCHAR($length)), text (unlimited text)*/
+       types that must be understood are: int32 (INTEGER), int64 (LONG INTEGER), seq32 (auto-incrementing int), seq64, bool (boolean), string:$length (text up to 255 chars, length is optional, default is 255; VARCHAR($length)), text (unlimited text)*/
        protected function dataType($type)
        {
                if($type=="int32")return "INTEGER";
                if($type=="int64")return "LONG INTEGER";
+               if($type=="bool")return "BOOLEAN";
                $tpa=explode(":",$type);
                if($tpa[0]=="string"){
                        if(isset($tpa[1]))
@@ -89,6 +94,7 @@ abstract class DbEngine
        protected function columnFlag($flag,$col)
        {
                if($flag=="primarykey")return "PRIMARY KEY";
+               if($flag=="null")return "NULL";
                if($flag=="notnull")return "NOT NULL";
                if($flag=="unique")return "NOT NULL UNIQUE";
                if($flag=="index")return "INDEX";
@@ -108,9 +114,14 @@ abstract class DbEngine
                                return "DEFAULT NULL";
                        return "DEFAULT ".$this->escapeString($tpa[1]);
                }
+               if($tpa[0]=="defaultbool"){
+                       if(count($tpa)<2)
+                               return "DEFAULT NULL";
+                       return "DEFAULT ".$this->escapeBool($tpa[1]);
+               }
        }
        
-       /**creates a SQL92 statement for creating a table*/
+       /**creates a SQL92 statement for creating a table; overwrite this to implement DB specific syntax*/
        protected function sqlCreateTable($tablename,$table)
        {
                $ret="CREATE TABLE ".$this->tableName($tablename)." (";
@@ -137,13 +148,13 @@ abstract class DbEngine
                return $ret;
        }
        
-       /**This function can be used to amend the column definitions of a table; if overwritten it must return a string*/
+       /**This function can be used to amend the column definitions of a table; if overwritten it must return a string; overwrite this to implement DB specific syntax*/
        protected function createTableExtras($tablename,$table)
        {
                return "";
        }
        
-       /**creates primary key statement for sqlCreateTable*/
+       /**creates primary key statement for sqlCreateTable; overwrite this to implement DB specific syntax*/
        protected function sqlCreateTablePrimaryKey(array $cols)
        {
                $ret="PRIMARY KEY(";
@@ -155,7 +166,16 @@ abstract class DbEngine
                return $ret;
        }
        
-       /**creates a SQL92 statement for inserts*/
+       /**creates a SQL92 statement for selects; overwrite this to implement DB specific syntax*/
+       public function sqlSelect($table,$cols,$where,$orderby)
+       {
+               $query="SELECT $cols FROM ".$this->tableName($table);
+               if($where!="")$query.=" WHERE ".$where;
+               if($orderby!="")$query.=" ".$orderby;
+               return $query;
+       }
+       
+       /**creates a SQL92 statement for inserts; overwrite this to implement DB specific syntax*/
        protected function sqlInsert($table,array $values)
        {
                global $dbScheme;
@@ -185,13 +205,13 @@ abstract class DbEngine
                return $ret;
        }
        
-       /**creates a SQL92 statement for deletes*/
+       /**creates a SQL92 statement for deletes; overwrite this to implement DB specific syntax*/
        protected function sqlDelete($table,$where)
        {
                return "DELETE FROM ".$this->tableName($table)." WHERE ".$where;
        }
        
-       /**creates a SQL92 statement for updates*/
+       /**creates a SQL92 statement for updates; overwrite this to implement DB specific syntax*/
        protected function sqlUpdate($table,array $values,$where)
        {
                global $dbScheme;
@@ -220,6 +240,24 @@ abstract class DbEngine
                return $ret;
        }
        
+       /**returns the SQL92 statement for beginning a transaction; overwrite this to implement DB specific syntax*/
+       public function sqlBeginTransaction()
+       {
+               return "BEGIN TRANSACTION";
+       }
+       
+       /**returns the SQL92 statement for committing a transaction; overwrite this to implement DB specific syntax*/
+       public function sqlCommitTransaction()
+       {
+               return "COMMIT TRANSACTION";
+       }
+       
+       /**returns the SQL92 statement for rolling a transaction back; overwrite this to implement DB specific syntax*/
+       public function sqlRollbackTransaction()
+       {
+               return "ROLLBACK TRANSACTION";
+       }
+       
        /**escapes integers; the default implementation just makes sure it is an int*/
        public function escapeInt($i)
        {
@@ -227,19 +265,38 @@ abstract class DbEngine
                return round($i + 0);
        }
        
-       /**escapes strings; the default uses addslashes and encloses the value in ''*/
+       /**escapes strings; the default uses addslashes and encloses the value in ''; it is recommended to overwrite this with the proper escaping procedure for the target DB*/
        public function escapeString($s)
        {
                if($s === false) return "NULL";
                return "'".addslashes($s)."'";
        }
        
-       /**escapes blobs; the default uses addslashes and encloses the value in ''*/
+       /**escapes blobs; the default uses addslashes and encloses the value in ''; it is recommended to overwrite this with the proper escaping procedure for the target DB*/
        public function escapeBlob($s)
        {
                if($s === false) return "NULL";
                return "'".addslashes($s)."'";
        }
+       
+       /**escapes a boolean value; the default translates 0, '0', 'f', 'false', 'no' to FALSE and numerics !=0, 't', 'true', 'yes' to TRUE; any other value (incl. the PHP constant false) is translated to NULL (exception: the constant true is treated as 'true')*/
+       public function escapeBool($s)
+       {
+               if(is_numeric($s)){
+                       if(($s+0)!=0)return "TRUE";
+                       else return "FALSE";
+               }
+               if($s===false)return "NULL";
+               if($s===true)return "TRUE";
+               switch(strtolower($s)){
+                       case "t":case "true":case "yes":case "y":
+                               return "TRUE";
+                       case "f":case "false":case "n":case "no":
+                               return "FALSE";
+                       default:
+                               return "NULL";
+               }
+       }
 
        /**returns a configuration setting*/
        public function getConfig($key)
@@ -275,27 +332,42 @@ abstract class DbEngine
                //iterate DB schema and create tables
                $tabs=$dbScheme->tableNames();
                for($i=0;$i<count($tabs);$i++){
+                       //create table
                        if(!$this->createTable($tabs[$i],$dbScheme->tableDefinition($tabs[$i]))){
                                print("DB Error while creating ".$tabs[$i].": ".$this->lastError()."<p>\n");
                                print("Last statement was: ".$this->sqlCreateTable($tabs[$i],$dbScheme->tableDefinition($tabs[$i]))."<p>\n");
                                $this->rollbackTransaction();
                                die("Unable to create database.");
                        }
+                       //insert defaults
+                       foreach($dbScheme->tableDefaults($tabs[$i]) as $def){
+                               $this->insert($tabs[$i],$def);
+                       }
                }
-               //insert some defaults
-               $this->insert("config",array("ckey"=>"MagicSmokeVersion","cval"=>$this->needVersion()));
-               $this->insert("config",array("ckey"=>"ValidVouchers","cval"=>"10 20 25 50"));
-               $this->insert("config",array("ckey"=>"OrderStop","cval"=>"24"));
-               $this->insert("config",array("ckey"=>"SaleStop","cval"=>"0"));
-               $this->insert("config",array("ckey"=>"TicketIDChars","cval"=>"10"));
-               $this->insert("config",array("ckey"=>"VoucherIDChars","cval"=>"10"));
-               $this->insert("host",array("hostname"=>"_any"));
-               $this->insert("host",array("hostname"=>"_anon"));
-               $this->insert("host",array("hostname"=>"_online"));
                //close transaction
                $this->commitTransaction();
        }
        
+       /**shows how the database would be created, used by admin.php only!!*/
+       public function showCreateDb()
+       {
+               global $dbScheme;
+               print("<h3>Database Creation SQL Script</h3>\n<pre>\n");
+               print(htmlentities($this->sqlBeginTransaction()).";\n");
+               //iterate DB schema and create tables
+               $tabs=$dbScheme->tableNames();
+               for($i=0;$i<count($tabs);$i++){
+                       //create table
+                       print(htmlentities($this->sqlCreateTable($tabs[$i],$dbScheme->tableDefinition($tabs[$i]))).";\n");
+                       //insert defaults
+                       foreach($dbScheme->tableDefaults($tabs[$i]) as $def){
+                               print(htmlentities($this->sqlInsert($tabs[$i],$def)).";\n");
+                       }
+               }
+               //close transaction
+               print(htmlentities($this->sqlCommitTransaction()).";\n<pre>\n");
+       }
+       
        /**returns the error string of the last operation*/
        public abstract function lastError();
 };
index b4644ac..2539f83 100644 (file)
@@ -70,24 +70,29 @@ class MysqlEngine extends DbEngine
        }
        public function beginTransaction()
        {
-               return mysqli_query($this->dbhdl,"BEGIN");
+               return mysqli_query($this->dbhdl,$this->sqlBeginTransaction());
        }
        
        public function commitTransaction()
        {
-               return mysqli_query($this->dbhdl,"COMMIT");
+               return mysqli_query($this->dbhdl,$this->sqlCommitTransaction());
        }
        
        public function rollbackTransaction()
        {
-               return mysqli_query($this->dbhdl,"ROLLBACK");
+               return mysqli_query($this->dbhdl,$this->sqlRollbackTransaction());
        }
        
+       public function sqlBeginTransaction(){return "BEGIN";}
+       
+       public function sqlCommitTransaction(){return "COMMIT";}
+       
+       public function sqlRollbackTransaction(){return "ROLLBACK";}
+
+       
        public function select($table,$cols,$where,$orderby="")
        {
-               $query="SELECT $cols FROM ".$this->tableName($table);
-               if($where!="")$query.=" WHERE ".$where;
-               if($orderby!="")$query.=" ".$orderby;
+               $query=$this->sqlSelect($table,$cols,$where,$orderby);
                $res=mysqli_query($this->dbhdl,$query);
                if($res===false)return false;
                $nr=mysqli_num_rows($res);
@@ -101,14 +106,22 @@ class MysqlEngine extends DbEngine
        
        protected function createTable($tn,$t)
        {
+               $sql=$this->sqlCreateTable($tn,$t);
+               return mysqli_query($this->dbhdl,$sql);
+       }
+       
+       protected function sqlCreateTable($tn,$t)
+       {
                $this->tableappend="";
-               $sql=$this->sqlCreateTable($tn,$t)." engine=".$this->engine." default charset=".$this->charset;
+               $sql=parent::sqlCreateTable($tn,$t)." engine=".$this->engine." default charset=".$this->charset;
 //             print("<pre>\n$sql\n</pre>\n");
-               return mysqli_query($this->dbhdl,$sql);
+               return $sql;
        }
        
        protected function createTableExtras($tablename,$table)
        {
+               //warning: this is rather dangerous, but safe at the moment since there is only
+               // one user of this function
                return $this->tableappend;
        }
        
index 69443da..0f26e56 100644 (file)
@@ -2,13 +2,29 @@
 /**This class contains a high-level description of the database structure*/
 class DbScheme {
        private static $scheme;
+       private static $preset;
+       private static $sversion;
+       
        function __construct()
        {
+               // ////////////////////
+               // version of this scheme
+               $this->sversion="00.02";
+               
+               // ////////////////////
                //configuration
                $this->scheme["config"]=array(
                        "ckey"=>array("string:32","primarykey"),
                        "cval"=>array("string")
                );
+               $this->preset["config"]=array(
+                       array("ckey"=>"MagicSmokeVersion","cval"=>$this->sversion),
+                       array("ckey"=>"ValidVouchers","cval"=>"10 20 25 50"),
+                       array("ckey"=>"OrderStop","cval"=>"24"),
+                       array("ckey"=>"SaleStop","cval"=>"0"),
+                       array("ckey"=>"TicketIDChars","cval"=>"10"),
+                       array("ckey"=>"VoucherIDChars","cval"=>"10")
+               );
                
                // ////////////////////
                // Machine Interface Stuff
@@ -19,6 +35,12 @@ class DbScheme {
                        //if hostkey is NULL it is a special host (_any, _anon, _online)
                        "hostkey"=>array("string")
                );
+               $this->preset["host"]=array(
+                       array("hostname"=>"_any"),
+                       array("hostname"=>"_anon"),
+                       array("hostname"=>"_online")
+               );
+
                //client users (ticket sellers, admins, etc.; for customers and web logins see below)
                $this->scheme["users"]=array(
                        "uname" => array("string:64","primarykey"),
@@ -55,7 +77,7 @@ class DbScheme {
                
                
                // //////////////////////
-               // Shared Stuff
+               // Shared Stuff (web & GUI-client)
                
                //rooms
                $this->scheme["room"]=array(
@@ -96,6 +118,15 @@ class DbScheme {
                        "customerid" => array("int32","unique","foreignkey:customer:customerid"),
                        "passwd" => array("string:64"),//salted SHA-1 hash of passwd
                );
+               
+               //kinds of shipping that are available (templates)
+               $this->scheme["shipping"]=array(
+                       "shipid" => array("seq32","primarykey"),
+                       "cost" => array("int32","notnull"), //default cost of this shipping type
+                       "canuseweb" => array("bool","default:false"), //is offered on web interface
+                       "canallusers" => array("bool","default:true") //all GUI users may select it
+               );
+               
                //orders by customers
                $this->scheme["order"]=array(
                        "orderid" => array("seq32","primarykey"),
@@ -115,7 +146,11 @@ class DbScheme {
                        "comments" => array("text"),
                        //how much has been paid already (including used vouchers)
                        //this is for comparison with the price fields in ticket and voucher tables
-                       "amountpaid" => array("int32")
+                       "amountpaid" => array("int32"),
+                       //shipping price
+                       "shippingcosts" => array("int32","default:0"),
+                       //pointer to shipping type (none per default, programmatic default is in config)
+                       "shippingtype" => array("int32","null","foreignkey:shipping:shipid")
                );
                //tickets
                $this->scheme["ticket"]=array(
@@ -187,6 +222,9 @@ class DbScheme {
                );
        }
        
+       /**return the version of this scheme*/
+       public function version(){return $this->sversion;}
+       
        /**return the tables to be created in order*/
        public function tableNames()
        {
@@ -209,6 +247,13 @@ class DbScheme {
                return array_keys($this->scheme[$tab]);
        }
        
+       /**return default lines of the table for the initialization; returns empty array if there are none*/
+       public function tableDefaults($tab)
+       {
+               if(isset($this->preset[$tab]))return $this->preset[$tab];
+               else return array();
+       }
+       
        /**return the type of a column, or false if it does not exist*/
        public function columnType($tab,$col)
        {