# HG changeset patch
# User Aaron Calero <aaron.calero@openbravo.com>
# Date 1428914305 -7200
#      Mon Apr 13 10:38:25 2015 +0200
# Node ID 741213b28c3c1b0627af1b15b86eddc3ea8b7c87
# Parent  bf8460ecff17d628aeb3d33bec6543e9d52e08dd
Fixed issue 29302: In paymentmethodcashup table one ticket can be added 2 times

Reapplied changes to the standard order flow to close tickets in a transactional way.

diff -r bf8460ecff17 -r 741213b28c3c web/org.openbravo.retail.posterminal/js/data/dataordersave.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordersave.js	Mon May 25 09:55:52 2015 +0000
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordersave.js	Mon Apr 13 10:38:25 2015 +0200
@@ -130,78 +130,75 @@
         OB.trace('Calculationg cashup information.');
 
         auxReceipt.clearWith(receipt);
-        OB.UTIL.cashUpReport(auxReceipt, function () {
-          OB.UTIL.calculateCurrentCash();
+        OB.Dal.transaction(function (tx) {
+          OB.UTIL.cashUpReport(auxReceipt, function () {
+            OB.UTIL.calculateCurrentCash(null, tx);
+            OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(receipt.get('documentnoSuffix'), receipt.get('quotationnoSuffix'), function () {
+              OB.trace('Saving receipt.');
+              OB.Dal.saveInTransaction(tx, receipt);
+            }, tx);
+          }, tx);
+        }, null, function () {
+          // success transaction...
+          OB.trace('Executing of post order save hook.');
 
-          OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(receipt.get('documentnoSuffix'), receipt.get('quotationnoSuffix'), function () {
-            OB.trace('Saving receipt.');
+          var successCallback = function (model) {
+              OB.trace('Sync process success.');
 
-            OB.Dal.save(receipt, function () {
+              //In case the processed document is a quotation, we remove its id so it can be reactivated
+              if (model && !_.isNull(model)) {
+                if (model.get('order') && model.get('order').get('isQuotation')) {
+                  model.get('order').set('oldId', model.get('order').get('id'));
+                  model.get('order').set('id', null);
+                  model.get('order').set('isbeingprocessed', 'N');
+                  OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_QuotationSaved', [currentDocNo]));
+                } else {
+                  if (isLayaway) {
+                    OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_MsgLayawaySaved', [currentDocNo]));
+                  } else {
+                    OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_MsgReceiptSaved', [currentDocNo]));
+                  }
+                }
+              }
 
-              var successCallback = function (model) {
-                  OB.trace('Sync process success.');
+              OB.trace('Order successfully removed.');
+              };
 
-                  //In case the processed document is a quotation, we remove its id so it can be reactivated
-                  if (model && !_.isNull(model)) {
-                    if (model.get('order') && model.get('order').get('isQuotation')) {
-                      model.get('order').set('oldId', model.get('order').get('id'));
-                      model.get('order').set('id', null);
-                      model.get('order').set('isbeingprocessed', 'N');
-                      OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_QuotationSaved', [currentDocNo]));
-                    } else {
-                      if (isLayaway) {
-                        OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_MsgLayawaySaved', [currentDocNo]));
-                      } else {
-                        OB.UTIL.showSuccess(OB.I18N.getLabel('OBPOS_MsgReceiptSaved', [currentDocNo]));
-                      }
-                    }
-                  }
+          if (OB.UTIL.HookManager.get('OBPOS_PostSyncReceipt')) {
+            //If there are elements in the hook, we are forced to execute the callback only after the synchronization process
+            //has been executed, to prevent race conditions with the callback processes (printing and deleting the receipt)
+            OB.trace('Execution Sync process.');
 
-                  OB.trace('Order successfully removed.');
-                  };
-
-              OB.trace('Executing of post order save hook.');
-
-              if (OB.UTIL.HookManager.get('OBPOS_PostSyncReceipt')) {
-                //If there are elements in the hook, we are forced to execute the callback only after the synchronization process
-                //has been executed, to prevent race conditions with the callback processes (printing and deleting the receipt)
-                OB.trace('Execution Sync process.');
-
-                OB.MobileApp.model.runSyncProcess(function () {
-                  OB.UTIL.HookManager.executeHooks('OBPOS_PostSyncReceipt', {
-                    receipt: auxReceipt
-                  }, function (args) {
-                    successCallback();
-                    if (eventParams && eventParams.callback) {
-                      eventParams.callback();
-                    }
-                  });
-                }, function () {
-                  OB.UTIL.HookManager.executeHooks('OBPOS_PostSyncReceipt', {
-                    receipt: auxReceipt
-                  }, function (args) {
-                    if (eventParams && eventParams.callback) {
-                      eventParams.callback();
-                    }
-                  });
-                });
-              } else {
-
-                OB.trace('Execution Sync process.');
-
-                //If there are no elements in the hook, we can execute the callback asynchronusly with the synchronization process
-                OB.MobileApp.model.runSyncProcess(function () {
-                  successCallback(model);
-                });
+            OB.MobileApp.model.runSyncProcess(function () {
+              OB.UTIL.HookManager.executeHooks('OBPOS_PostSyncReceipt', {
+                receipt: auxReceipt
+              }, function (args) {
+                successCallback();
                 if (eventParams && eventParams.callback) {
                   eventParams.callback();
                 }
-              }
+              });
+            }, function () {
+              OB.UTIL.HookManager.executeHooks('OBPOS_PostSyncReceipt', {
+                receipt: auxReceipt
+              }, function (args) {
+                if (eventParams && eventParams.callback) {
+                  eventParams.callback();
+                }
+              });
+            });
+          } else {
 
-            }, function () {
-              //We do nothing: we don't need to alert the user, as the order is still present in the database, so it will be resent as soon as the user logs in again
+            OB.trace('Execution Sync process.');
+
+            //If there are no elements in the hook, we can execute the callback asynchronusly with the synchronization process
+            OB.MobileApp.model.runSyncProcess(function () {
+              successCallback(model);
             });
-          });
+            if (eventParams && eventParams.callback) {
+              eventParams.callback();
+            }
+          }
         });
       });
     }, this);
diff -r bf8460ecff17 -r 741213b28c3c web/org.openbravo.retail.posterminal/js/login/model/login-model.js
--- a/web/org.openbravo.retail.posterminal/js/login/model/login-model.js	Mon May 25 09:55:52 2015 +0000
+++ b/web/org.openbravo.retail.posterminal/js/login/model/login-model.js	Mon Apr 13 10:38:25 2015 +0200
@@ -707,8 +707,9 @@
      * Save the new values if are higher than the last known values
      * - the minimum sequence number can only grow
      */
-    saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix, callback) {
-      var me = this;
+    saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix, callback, tx) {
+      var me = this,
+          processDocumentSequenceList;
       if (me.restartingDocNo === true) {
         return;
       }
@@ -725,10 +726,7 @@
         this.quotationnoThreshold = quotationnoSuffix;
       }
 
-      // verify the database values
-      OB.Dal.find(OB.Model.DocumentSequence, {
-        'posSearchKey': this.get('terminal').searchKey
-      }, function (documentSequenceList) {
+      processDocumentSequenceList = function (documentSequenceList) {
 
         var docSeq;
         if (documentSequenceList && documentSequenceList.length > 0) {
@@ -758,7 +756,7 @@
         // update the database
         docSeq.set('documentSequence', me.documentnoThreshold);
         docSeq.set('quotationDocumentSequence', me.quotationnoThreshold);
-        OB.Dal.save(docSeq, function () {
+        OB.Dal.saveInTransaction(tx, docSeq, function () {
           if (callback) {
             callback();
           }
@@ -766,8 +764,12 @@
         }, function () {
           me.restartingDocNo = false;
         });
+      };
 
-      }, function () {
+      // verify the database values
+      OB.Dal.findInTransaction(tx, OB.Model.DocumentSequence, {
+        'posSearchKey': this.get('terminal').searchKey
+      }, processDocumentSequenceList, function () {
         me.restartingDocNo = false;
       });
     },
@@ -776,11 +778,11 @@
      * Updates the document sequence. This method should only be called when an order has been sent to the server
      * If the order is a quotation, only update the quotationno
      */
-    updateDocumentSequenceWhenOrderSaved: function (documentnoSuffix, quotationnoSuffix, callback) {
+    updateDocumentSequenceWhenOrderSaved: function (documentnoSuffix, quotationnoSuffix, callback, tx) {
       if (quotationnoSuffix >= 0) {
         documentnoSuffix = -1;
       }
-      this.saveDocumentSequence(documentnoSuffix, quotationnoSuffix, callback);
+      this.saveDocumentSequence(documentnoSuffix, quotationnoSuffix, callback, tx);
     },
 
     // get the first document number available
diff -r bf8460ecff17 -r 741213b28c3c web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js
--- a/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js	Mon May 25 09:55:52 2015 +0000
+++ b/web/org.openbravo.retail.posterminal/js/utils/cashUpReportUtils.js	Mon Apr 13 10:38:25 2015 +0200
@@ -1,6 +1,6 @@
 /*
  ************************************************************************************
- * Copyright (C) 2012 Openbravo S.L.U.
+ * Copyright (C) 2012-2015 Openbravo S.L.U.
  * Licensed under the Openbravo Commercial License version 1.0
  * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
  * or in the legal folder of this module distribution.
@@ -13,27 +13,27 @@
 
   OB.UTIL = window.OB.UTIL || {};
 
-  function findAndSave(cashuptaxes, i, finishCallback) {
+  function findAndSave(cashuptaxes, i, finishCallback, tx) {
 
     if (i < cashuptaxes.length) {
-      OB.Dal.find(OB.Model.TaxCashUp, {
+      OB.Dal.findInTransaction(tx, OB.Model.TaxCashUp, {
         'cashup_id': cashuptaxes[i].cashupID,
         'name': cashuptaxes[i].taxName,
         'orderType': cashuptaxes[i].taxOrderType
       }, function (tax) {
         if (tax.length === 0) {
-          OB.Dal.save(new OB.Model.TaxCashUp({
+          OB.Dal.saveInTransaction(tx, new OB.Model.TaxCashUp({
             name: cashuptaxes[i].taxName,
             amount: cashuptaxes[i].taxAmount,
             orderType: cashuptaxes[i].taxOrderType,
             cashup_id: cashuptaxes[i].cashupID
           }), function () {
-            findAndSave(cashuptaxes, i + 1, finishCallback);
+            findAndSave(cashuptaxes, i + 1, finishCallback, tx);
           }, null);
         } else {
           tax.at(0).set('amount', OB.DEC.add(tax.at(0).get('amount'), cashuptaxes[i].taxAmount));
-          OB.Dal.save(tax.at(0), function () {
-            findAndSave(cashuptaxes, i + 1, finishCallback);
+          OB.Dal.saveInTransaction(tx, tax.at(0), function () {
+            findAndSave(cashuptaxes, i + 1, finishCallback, tx);
           }, null);
         }
       });
@@ -44,8 +44,9 @@
     }
   }
 
-  function updateCashUpInfo(cashUp, receipt, j, callback) {
+  function updateCashUpInfo(cashUp, receipt, j, callback, tx) {
     var cashuptaxes, order, orderType, gross, i, taxOrderType, taxAmount, auxPay;
+
     if (j < receipt.length) {
       order = receipt[j];
       orderType = order.get('orderType');
@@ -78,7 +79,7 @@
           }
         });
         cashUp.at(0).set('totalRetailTransactions', OB.DEC.sub(cashUp.at(0).get('grossSales'), cashUp.at(0).get('grossReturns')));
-        OB.Dal.save(cashUp.at(0), null, null);
+        OB.Dal.saveInTransaction(tx, cashUp.at(0), null, null);
 
         // group and sum the taxes
         cashuptaxes = [];
@@ -117,7 +118,7 @@
           });
         });
 
-        OB.Dal.find(OB.Model.PaymentMethodCashUp, {
+        OB.Dal.findInTransaction(tx, OB.Model.PaymentMethodCashUp, {
           'cashup_id': cashUp.at(0).get('id')
         }, function (payMthds) { //OB.Dal.find success
           _.each(order.get('payments').models, function (payment) {
@@ -134,12 +135,13 @@
             } else {
               auxPay.set('totalSales', OB.DEC.add(auxPay.get('totalSales'), payment.get('amount')));
             }
-            OB.Dal.save(auxPay, null, null);
+            OB.Dal.saveInTransaction(tx, auxPay, null, null);
           }, this);
           findAndSave(cashuptaxes, 0, function () {
-            OB.UTIL.composeCashupInfo(cashUp, null, null);
-            updateCashUpInfo(cashUp, receipt, j + 1, callback);
-          });
+            OB.UTIL.composeCashupInfo(cashUp, null, function () {
+              updateCashUpInfo(cashUp, receipt, j + 1, callback, tx);
+            }, tx);
+          }, tx);
         });
       }
     } else if (typeof callback === 'function') {
@@ -147,15 +149,16 @@
     }
   }
 
-  OB.UTIL.cashUpReport = function (receipt, callback) {
+  OB.UTIL.cashUpReport = function (receipt, callback, tx) {
     var auxPay, orderType, taxOrderType, taxAmount, gross;
     if (!Array.isArray(receipt)) {
       receipt = [receipt];
     }
-    OB.Dal.find(OB.Model.CashUp, {
+
+    OB.Dal.findInTransaction(tx, OB.Model.CashUp, {
       'isprocessed': 'N'
     }, function (cashUp) {
-      updateCashUpInfo(cashUp, receipt, 0, callback);
+      updateCashUpInfo(cashUp, receipt, 0, callback, tx);
     });
   };
 
@@ -467,12 +470,13 @@
       });
     }
   };
-  OB.UTIL.calculateCurrentCash = function (callback) {
+  OB.UTIL.calculateCurrentCash = function (callback, tx) {
     var me = this;
-    OB.Dal.find(OB.Model.CashUp, {
+
+    OB.Dal.findInTransaction(tx, OB.Model.CashUp, {
       'isprocessed': 'N'
     }, function (cashUp) {
-      OB.Dal.find(OB.Model.PaymentMethodCashUp, {
+      OB.Dal.findInTransaction(tx, OB.Model.PaymentMethodCashUp, {
         'cashup_id': cashUp.at(0).get('id')
       }, function (payMthds) { //OB.Dal.find success
         var payMthdsCash;
@@ -551,15 +555,12 @@
     }, this);
   };
 
-  OB.UTIL.saveComposeInfo = function (me, callback, objToSend, cashUp) {
+  OB.UTIL.saveComposeInfo = function (me, callback, objToSend, cashUp, tx) {
+
     cashUp.at(0).set('userId', OB.MobileApp.model.get('context').user.id);
     objToSend.set('userId', OB.MobileApp.model.get('context').user.id);
     cashUp.at(0).set('objToSend', JSON.stringify(objToSend));
-    if (callback) {
-      OB.Dal.save(cashUp.at(0), callback(me), null);
-    } else {
-      OB.Dal.save(cashUp.at(0), null, null);
-    }
+    OB.Dal.saveInTransaction(tx, cashUp.at(0), callback ? callback(me) : null, null);
   };
   OB.UTIL.getTaxCashUp = function (taxcashups, objToSend, cashUp) {
     _.each(taxcashups.models, function (currentTax) {
@@ -580,7 +581,7 @@
     }, this);
   };
 
-  OB.UTIL.composeCashupInfo = function (cashUp, me, callback) {
+  OB.UTIL.composeCashupInfo = function (cashUp, me, callback, tx) {
     var objToSend = new Backbone.Model({
       posterminal: OB.MobileApp.model.get('terminal').id,
       id: cashUp.at(0).get('id'),
@@ -599,19 +600,19 @@
     });
 
     //process the payment method cash ups
-    OB.Dal.find(OB.Model.PaymentMethodCashUp, {
+    OB.Dal.findInTransaction(tx, OB.Model.PaymentMethodCashUp, {
       'cashup_id': cashUp.at(0).get('id'),
       '_orderByClause': 'name asc'
     }, function (payMthds) {
       OB.UTIL.getPaymethodCashUp(payMthds, objToSend, cashUp);
 
       //process the taxs cash ups
-      OB.Dal.find(OB.Model.TaxCashUp, {
+      OB.Dal.findInTransaction(tx, OB.Model.TaxCashUp, {
         'cashup_id': cashUp.at(0).get('id'),
         '_orderByClause': 'name asc'
       }, function (taxcashups) {
         OB.UTIL.getTaxCashUp(taxcashups, objToSend, cashUp);
-        OB.UTIL.saveComposeInfo(me, callback, objToSend, cashUp);
+        OB.UTIL.saveComposeInfo(me, callback, objToSend, cashUp, tx);
       });
     });
   };
