Improved transactions support (multilevel).
authorJanusz Dobrowolski <janusz@frontaccounting.eu>
Tue, 9 Feb 2010 13:10:02 +0000 (13:10 +0000)
committerJanusz Dobrowolski <janusz@frontaccounting.eu>
Tue, 9 Feb 2010 13:10:02 +0000 (13:10 +0000)
includes/db/connect_db.inc
includes/db/sql_functions.inc
includes/errors.inc
sales/includes/cart_class.inc

index 203883b084e0a1fdb90f8c8be1296618cd4c162e..3e0d551f2888beef86d29c29466e19da01c999a2 100644 (file)
 
 function set_global_connection()
 {
-       global $db;
+       global $db, $transaction_level;
+
+       cancel_transaction(); // cancel all aborted transactions if any
+       $transaction_level = 0;
 
        $db = $_SESSION["wa_current_user"]->get_db_connection();
 }
index 0fa479dc2b946754157a383025bd3ef93d70e234..2e5a28f4595abf9a2d3b236247930603c5fbba94 100644 (file)
 //
 //     General database functions common for all modules.
 //
-//-------------------------------------------------------------------  
+//-------------------------------------------------------------------
+// Multilevel transaction control.
+//
+
 function begin_transaction()
 {
-       db_query("BEGIN", "could not start a transaction");
+       global $transaction_level; // set in set_global_connection()
+
+       if (!$transaction_level) {
+               error_log('begin');
+               db_query("BEGIN", "could not start a transaction");
+       }
+       $transaction_level++;
+       error_log("level:$transaction_level");
 }
 
 function commit_transaction()
 {
-       db_query("COMMIT", "could not commit a transaction");
+       global $transaction_level;
+
+       $transaction_level--;
+
+       if (!$transaction_level) {
+               error_log('commit');
+               db_query("COMMIT", "could not commit a transaction");
+       }
+       error_log("level:$transaction_level");
 }
 
+/*
+       This function is called on end of script execution to cancel
+       all aborted transactions (if any)
+*/
 function cancel_transaction()
 {
-       db_query("ROLLBACK", "could not cancel a transaction"); 
+       global $transaction_level;
+
+       if ($transaction_level) {
+               error_log('rollback');
+               db_query("ROLLBACK", "could not cancel a transaction"); 
+       } else
+               error_log("no transactions");
+
 }
+
 //-----------------------------------------------------------------------------
 //     Update record activity status.
 //
index 551d32e4438a2c5b63f260d2e5adf84ac96be76d..9e0dba2e87fc99edf3694e96528e6096e74c31b3 100644 (file)
@@ -94,13 +94,16 @@ function error_box() {
 /*
        Helper to avoid sparse log notices.
 */
-function end_flush () {
-       global $Ajax;
+function end_flush() {
+       global $Ajax, $transaction_level;
 
        if (isset($Ajax))
                $Ajax->run();
        // flush all output buffers (works also with exit inside any div levels)
        while(ob_get_level()) ob_end_flush();
+
+       // if any transaction was aborted unexpectedly rollback changes
+       cancel_transaction();
 }
 
 function display_db_error($msg, $sql_statement=null, $exit=true)
index 68166e9812a8443044233e48993c1d8cd792ad41..3566d686ff14bdd4c2bb82ee91d9b686d9da9f66 100644 (file)
@@ -209,6 +209,7 @@ class cart
        // Makes parent documents for direct delivery/invoice by recurent call.
        // $policy - 0 or 1:  writeoff/return for IV, back order/cancel for DN
        function write($policy=0) {
+               begin_transaction(); // prevents partial database changes in case of direct delivery/invoice
                if (count($this->src_docs) == 0 && ($this->trans_type == ST_SALESINVOICE || $this->trans_type == ST_CUSTDELIVERY)) {
                        // this is direct document - first add parent
                        $src = (PHP_VERSION<5) ? $this : clone( $this ); // make local copy of this cart
@@ -236,18 +237,20 @@ class cart
                }
                switch($this->trans_type) {
                        case ST_SALESINVOICE:
-                               return write_sales_invoice($this);
+                               write_sales_invoice($this); break;
                        case ST_CUSTCREDIT:
-                               return write_credit_note($this, $policy);
+                               write_credit_note($this, $policy); break;
                        case ST_CUSTDELIVERY:
-                               return write_sales_delivery($this, $policy);
+                               write_sales_delivery($this, $policy); break;
                        case ST_SALESORDER:
                        case ST_SALESQUOTE:
                                if ($this->trans_no==0) // new document
-                                       return add_sales_order($this);
+                                       add_sales_order($this);
                                else
-                                       return update_sales_order($this);
+                                       update_sales_order($this);
                }
+
+               commit_transaction();
        }
 
        function set_customer($customer_id, $customer_name, $currency, $discount, $payment, $cdiscount=0)