Project:
| View Issue Details[ Jump to Notes ] | [ Issue History ] [ Print ] | |||||||
| ID | ||||||||
| 0027813 | ||||||||
| Type | Category | Severity | Reproducibility | Date Submitted | Last Update | |||
| backport | [Retail Modules] Web POS | major | N/A | 2014-10-09 13:05 | 2016-05-25 12:28 | |||
| Reporter | Orekaria | View Status | public | |||||
| Assigned To | Orekaria | |||||||
| Priority | high | Resolution | no change required | Fixed in Version | ||||
| Status | closed | Fix in branch | pi | Fixed in SCM revision | ||||
| Projection | none | ETA | none | Target Version | RR14Q2.3 | |||
| OS | Any | Database | Any | Java version | ||||
| OS Version | Database version | Ant version | ||||||
| Product Version | SCM revision | |||||||
| Merge Request Status | ||||||||
| Review Assigned To | Orekaria | |||||||
| OBNetwork customer | No | |||||||
| Support ticket | ||||||||
| Regression level | ||||||||
| Regression date | ||||||||
| Regression introduced in release | ||||||||
| Regression introduced by commit | ||||||||
| Triggers an Emergency Pack | No | |||||||
| Summary | 0027813: Backport the document number fixes introduced in Q4 to Q2.4/Q3 | |||||||
| Description | Backport the document number (aka docno) fixes introduced in Q4 to Q2.4/Q3 - no duplicated docnos after refreshing or after sale, logout, login - no gaps between docnos (if the user do not create empty receipts and then finishes the last of those receipts) - synchronization with the server to get the last docno when login - navigating to cashup/cash management do not create docno gaps - prefix change: if the prefix is changed in the server the docno number is updated after relogin - quotations: the same improvements have been made for quotations | |||||||
| Steps To Reproduce | NA | |||||||
| Tags | No tags attached. | |||||||
| Attached Files | # HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1410103971 -7200
# Sun Sep 07 17:32:51 2014 +0200
# Node ID 02d20cd9244444c3206328a673d479270db94a69
# Parent cd8c9b63d38f8fe66d8e22b9bcfa0f0ccb497e09
Fixes issue 27548: OB.MobileApp.model.orderList points to the order list and their methods
diff -r cd8c9b63d38f -r 02d20cd92444 web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Wed Sep 17 17:37:19 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Sun Sep 07 17:32:51 2014 +0200
@@ -296,6 +296,7 @@
});
this.set('order', receipt);
orderList = new OB.Collection.OrderList(receipt);
+ OB.MobileApp.model.orderList = orderList;
this.set('orderList', orderList);
this.set('customer', new OB.Model.BusinessPartner());
this.set('customerAddr', new OB.Model.BPLocation());
# HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1410023914 -7200
# Sat Sep 06 19:18:34 2014 +0200
# Node ID cfe16f6aae3ebd800bc3c05886a8169b1c92437b
# Parent 02d20cd9244444c3206328a673d479270db94a69
Fixes issue 27309 and issue 27476: A new document sequence algorithm has been introduced to preserve consecutive document numbers
This logic:
- can handle the regular activity with the WebPOS: navigating, adding, deleting, changing orders, etc.
- it does not fill gaps that the user do not want to. e.g: if order 001 is paid, then 3 empty orders are created and then the 004 is paid; 005 will be the next valid document number
- synchronizes the document number with the server each time the terminal info is updated, which is, as of now, after login, every page refresh and every x minutes
- cannot handle 2 or more terminals with the same id, running at the same time
diff -r 02d20cd92444 -r cfe16f6aae3e web/org.openbravo.retail.posterminal/js/data/dataordersave.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordersave.js Sun Sep 07 17:32:51 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordersave.js Sat Sep 06 19:18:34 2014 +0200
@@ -37,7 +37,8 @@
}
this.receipt.set('hasbeenpaid', 'Y');
- OB.UTIL.updateDocumentSequenceInDB(docno);
+ OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(this.receipt.get('documentnoSuffix'), this.receipt.get('quotationnoSuffix'));
+
delete this.receipt.attributes.json;
this.receipt.set('timezoneOffset', creationDate.getTimezoneOffset());
@@ -126,7 +127,7 @@
this.receipt.set('hasbeenpaid', 'Y');
- OB.UTIL.updateDocumentSequenceInDB(docno);
+ OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(this.receipt.get('documentnoSuffix'), this.receipt.get('quotationnoSuffix'));
delete this.receipt.attributes.json;
this.receipt.set('timezoneOffset', creationDate.getTimezoneOffset());
diff -r 02d20cd92444 -r cfe16f6aae3e web/org.openbravo.retail.posterminal/js/login/model/login-model.js
--- a/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Sun Sep 07 17:32:51 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Sat Sep 06 19:18:34 2014 +0200
@@ -91,7 +91,12 @@
});
}
} else if (data[0]) {
+ // load the OB.MobileApp.model.get('terminal') attributes
terminalModel.set(me.properties[0], data[0]);
+
+ // update the local database with the document sequence received
+ OB.MobileApp.model.saveDocumentSequence(OB.MobileApp.model.get('terminal').lastDocumentNumber, OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber);
+
window.localStorage.setItem('terminalId', data[0].id);
terminalModel.set('useBarcode', terminalModel.get('terminal').terminalType.usebarcodescanner);
OB.MobileApp.view.scanningFocus(true);
@@ -402,11 +407,10 @@
}
});
- this.on('seqNoReady', function () {
- this.trigger('ready'); //NAVIGATE
- }, this);
+ // force the initialization of the document sequence info
+ this.saveDocumentSequence();
- this.setDocumentSequence();
+ this.trigger('ready');
},
cleanSessionInfo: function () {
@@ -451,136 +455,145 @@
});
},
- compareDocSeqWithPendingOrdersAndSave: function (maxDocumentSequence, maxQuotationDocumentSequence) {
- var orderDocNo, quotationDocNo;
- // compare the last document number returned from the ERP with
- // the last document number of the unprocessed pending lines (if any)
- OB.Dal.find(OB.Model.Order, {}, function (fetchedOrderList) {
- var criteria, maxDocumentSequencePendingOrders;
- if (!fetchedOrderList || fetchedOrderList.length === 0) {
- // There are no pending orders, the initial document sequence
- // will be the one fetched from the database
- OB.MobileApp.model.saveDocumentSequenceAndGo(maxDocumentSequence, maxQuotationDocumentSequence);
- } else {
- // There are pending orders. The document sequence will be set
- // to the maximum of the pending order document sequence and the
- // document sequence retrieved from the server
- maxDocumentSequencePendingOrders = OB.MobileApp.model.getMaxDocumentSequenceFromPendingOrders(fetchedOrderList.models);
- if (maxDocumentSequencePendingOrders.orderDocNo > maxDocumentSequence) {
- orderDocNo = maxDocumentSequencePendingOrders.orderDocNo;
- } else {
- orderDocNo = maxDocumentSequence;
+ // these variables will keep the minimum value that the document order could have
+ // they feed from the local database, and the server
+ documentnoThreshold: -1,
+ quotationnoThreshold: -1,
+
+ /**
+ * Save the new values if are higher than the last knowwn values
+ * - the minimum sequence number can only grow
+ */
+ saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix) {
+ var me = this;
+
+ /**
+ * If for whatever reason the maxSuffix is not the current order suffix (most likely, the server returning a higher docno value)
+ * 1. if there is a current order
+ * 2. and has no lines (no product added, etc)
+ * 3. if the current order suffix is lower than the minNumbers
+ * 4. delete the order
+ */
+ var synchronizeCurrentOrder = function () {
+ var orderlist = OB.MobileApp.model.orderList;
+ if (orderlist && orderlist.models.length > 0 && orderlist.current) {
+ if (orderlist.current.get('lines') && orderlist.current.get('lines').length === 0) {
+ if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold) {
+ orderlist.deleteCurrent();
+ }
+ }
}
- if (maxDocumentSequencePendingOrders.quotationDocNo > maxQuotationDocumentSequence) {
- quotationDocNo = maxDocumentSequencePendingOrders.quotationDocNo;
- } else {
- quotationDocNo = maxQuotationDocumentSequence;
- }
- OB.MobileApp.model.saveDocumentSequenceAndGo(orderDocNo, quotationDocNo);
- }
- }, function () {
- // If c_order does not exist yet, go with the sequence
- // number fetched from the server
- OB.MobileApp.model.saveDocumentSequenceAndGo(maxDocumentSequence, maxQuotationDocumentSequence);
- });
- },
+ };
- getMaxDocumentSequenceFromPendingOrders: function (pendingOrders) {
- var nPreviousOrders = pendingOrders.length,
- maxDocumentSequence = OB.MobileApp.model.get('terminal').lastDocumentNumber,
- maxQuotationDocumentSequence = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber,
- orderCompleteDocumentNo, orderDocumentSequence, i;
- for (i = 0; i < nPreviousOrders; i++) {
- orderCompleteDocumentNo = pendingOrders[i].get('documentNo');
- if (!pendingOrders[i].get('isQuotation')) {
- orderDocumentSequence = OB.UTIL.getNumberOfSequence(pendingOrders[i].get('documentNo'), false);
- if (orderDocumentSequence > maxDocumentSequence) {
- maxDocumentSequence = orderDocumentSequence;
- }
- } else {
- orderDocumentSequence = OB.UTIL.getNumberOfSequence(pendingOrders[i].get('documentNo'), true);
- if (orderDocumentSequence > maxQuotationDocumentSequence) {
- maxQuotationDocumentSequence = orderDocumentSequence;
- }
- }
+ // verify that the values are higher than the local variables
+ if (documentnoSuffix > this.documentnoThreshold) {
+ this.documentnoThreshold = documentnoSuffix;
}
- return {
- orderDocNo: maxDocumentSequence,
- quotationDocNo: maxQuotationDocumentSequence
- };
- },
+ if (quotationnoSuffix > this.quotationnoThreshold) {
+ this.quotationnoThreshold = quotationnoSuffix;
+ }
- saveDocumentSequenceAndGo: function (documentSequence, quotationDocumentSequence) {
- this.set('documentsequence', documentSequence);
- this.set('quotationDocumentSequence', quotationDocumentSequence);
- this.trigger('seqNoReady');
- },
+ // verify the database values
+ OB.Dal.find(OB.Model.DocumentSequence, {
+ 'posSearchKey': this.get('terminal').searchKey
+ }, function (documentSequenceList) {
- setDocumentSequence: function () {
- // Obtains the persisted document number (documentno of the last processed order)
- OB.Dal.find(OB.Model.DocumentSequence, {
- 'posSearchKey': OB.MobileApp.model.terminalName
- }, function (documentsequence) {
- var lastInternalDocumentSequence, lastInternalQuotationSequence, max, maxquote;
- if (documentsequence && documentsequence.length > 0) {
- lastInternalDocumentSequence = documentsequence.at(0).get('documentSequence');
- lastInternalQuotationSequence = documentsequence.at(0).get('quotationDocumentSequence');
- // Compares the persisted document number with the fetched from the server
- if (lastInternalDocumentSequence > OB.MobileApp.model.get('terminal').lastDocumentNumber) {
- max = lastInternalDocumentSequence;
- } else {
- max = OB.MobileApp.model.get('terminal').lastDocumentNumber;
- }
- if (lastInternalQuotationSequence > OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber) {
- maxquote = lastInternalQuotationSequence;
- } else {
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- }
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- } else {
- max = OB.MobileApp.model.get('terminal').lastDocumentNumber;
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- }
-
- }, function () {
- var max = OB.MobileApp.model.get('terminal').lastDocumentNumber,
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- });
- },
-
- saveDocumentSequenceInDB: function () {
- var me = this,
- documentSequence = this.get('documentsequence'),
- quotationDocumentSequence = this.get('quotationDocumentSequence'),
- criteria = {
- 'posSearchKey': this.get('terminal').searchKey
- };
- OB.Dal.find(OB.Model.DocumentSequence, criteria, function (documentSequenceList) {
var docSeq;
- if (documentSequenceList && documentSequenceList.length !== 0) {
+ if (documentSequenceList && documentSequenceList.length > 0) {
// There can only be one documentSequence model in the list (posSearchKey is unique)
docSeq = documentSequenceList.models[0];
- // There exists already a document sequence, update it
- docSeq.set('documentSequence', documentSequence);
- docSeq.set('quotationDocumentSequence', quotationDocumentSequence);
+ // verify if the new values are higher
+ if (docSeq.get('documentSequence') > me.documentnoThreshold) {
+ me.documentnoThreshold = docSeq.get('documentSequence');
+ }
+ if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold) {
+ me.quotationnoThreshold = docSeq.get('quotationDocumentSequence');
+ }
} else {
// There is not a document sequence for the pos, create it
docSeq = new OB.Model.DocumentSequence();
docSeq.set('posSearchKey', me.get('terminal').searchKey);
- docSeq.set('documentSequence', documentSequence);
- docSeq.set('quotationDocumentSequence', quotationDocumentSequence);
}
- OB.Dal.save(docSeq, null, function () {
- OB.error(arguments);
+
+ // update the database
+ docSeq.set('documentSequence', me.documentnoThreshold);
+ docSeq.set('quotationDocumentSequence', me.quotationnoThreshold);
+ OB.Dal.save(docSeq, function () {
+ synchronizeCurrentOrder();
+ }, function () {
+ // nothing to do
});
+
+ }, function () {
+ OB.debug("The 'c_document_sequence' table is locked");
});
},
+ /**
+ * 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) {
+ if (quotationnoSuffix >= 0) {
+ documentnoSuffix = -1;
+ }
+ this.saveDocumentSequence(documentnoSuffix, quotationnoSuffix);
+ },
+
+ // get the first document number available
+ getLastDocumentnoSuffixInOrderlist: function () {
+ var lastSuffix = null;
+ if (OB.MobileApp.model.orderList.length > 0) {
+ var i = OB.MobileApp.model.orderList.models.length - 1;
+ while (lastSuffix === null && i >= 0) {
+ var order = OB.MobileApp.model.orderList.models[i];
+ if (!order.get('isPaid') && !order.get('isQuotation')) {
+ lastSuffix = order.get('documentnoSuffix');
+ }
+ i--;
+ }
+ }
+ if (lastSuffix === null || lastSuffix < this.documentnoThreshold) {
+ lastSuffix = this.documentnoThreshold;
+ }
+ return lastSuffix;
+ },
+ // get the first quotation number available
+ getLastQuotationnoSuffixInOrderlist: function () {
+ var lastSuffix = null;
+ if (OB.MobileApp.model.orderList.length > 0) {
+ var i = OB.MobileApp.model.orderList.models.length - 1;
+ while (lastSuffix === null && i >= 0) {
+ var order = OB.MobileApp.model.orderList.models[i];
+ if (order.get('isQuotation')) {
+ lastSuffix = order.get('quotationnoSuffix');
+ }
+ i--;
+ }
+ }
+ if (lastSuffix === null || lastSuffix < this.quotationnoThreshold) {
+ lastSuffix = this.quotationnoThreshold;
+ }
+ return lastSuffix;
+ },
+
+ // call this method to get a new order document number
+ getNextDocumentno: function () {
+ var next = this.getLastDocumentnoSuffixInOrderlist() + 1;
+ return {
+ documentnoSuffix: next,
+ documentNo: OB.MobileApp.model.get('terminal').docNoPrefix + '/' + OB.UTIL.padNumber(next, 7)
+ };
+ },
+ // call this method to get a new quotation document number
+ getNextQuotationno: function () {
+ var next = this.getLastQuotationnoSuffixInOrderlist() + 1;
+ return {
+ quotationnoSuffix: next,
+ documentNo: OB.MobileApp.model.get('terminal').quotationDocNoPrefix + '/' + OB.UTIL.padNumber(next, 7)
+ };
+ },
+
getPaymentName: function (key) {
if (this.paymentnames[key] && this.paymentnames[key].payment && this.paymentnames[key].payment._identifier) {
return this.paymentnames[key].payment._identifier;
diff -r 02d20cd92444 -r cfe16f6aae3e web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js Sun Sep 07 17:32:51 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js Sat Sep 06 19:18:34 2014 +0200
@@ -267,6 +267,8 @@
this.set('posTerminal', attributes.posTerminal);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, attributes['posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER]);
this.set('orderDate', new Date(attributes.orderDate));
+ this.set('documentnoSuffix', attributes.documentnoSuffix);
+ this.set('quotationnoSuffix', attributes.quotationnoSuffix);
this.set('documentNo', attributes.documentNo);
this.set('undo', attributes.undo);
this.set('bp', new Backbone.Model(attributes.bp));
@@ -582,6 +584,8 @@
this.set('posTerminal', null);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, null);
this.set('orderDate', new Date());
+ this.set('documentnoSuffix', -1);
+ this.set('quotationnoSuffix', -1);
this.set('documentNo', '');
this.set('undo', null);
this.set('bp', null);
@@ -1373,10 +1377,9 @@
this.set('isPaid', false);
this.set('isEditable', true);
this.set('orderDate', new Date());
- documentseq = OB.POS.modelterminal.get('documentsequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('documentsequence', documentseq);
- this.set('documentNo', OB.POS.modelterminal.get('terminal').docNoPrefix + '/' + documentseqstr);
+ var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
+ this.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
+ this.set('documentNo', nextDocumentno.documentNo);
this.set('posTerminal', OB.POS.modelterminal.get('terminal').id);
this.save();
if (updatePrices) {
@@ -1681,10 +1684,9 @@
order.set('isLayaway', false);
order.set('taxes', null);
- documentseq = OB.POS.modelterminal.get('documentsequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('documentsequence', documentseq);
- order.set('documentNo', OB.POS.modelterminal.get('terminal').docNoPrefix + '/' + documentseqstr);
+ var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
+ order.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
+ order.set('documentNo', nextDocumentno.documentNo);
order.set('bp', OB.POS.modelterminal.get('businessPartner'));
order.set('print', true);
@@ -1883,10 +1885,10 @@
this.current.set('isQuotation', true);
this.current.set('generateInvoice', false);
this.current.set('documentType', OB.POS.modelterminal.get('terminal').terminalType.documentTypeForQuotations);
- documentseq = OB.POS.modelterminal.get('quotationDocumentSequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('quotationDocumentSequence', documentseq);
- this.current.set('documentNo', OB.POS.modelterminal.get('terminal').quotationDocNoPrefix + '/' + documentseqstr);
+ var nextQuotationno = OB.MobileApp.model.getNextQuotationno();
+ this.current.set('quotationnoSuffix', nextQuotationno.quotationnoSuffix);
+ this.current.set('documentNo', nextQuotationno.documentNo);
+
this.add(this.current);
this.loadCurrent();
},
diff -r 02d20cd92444 -r cfe16f6aae3e web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Sun Sep 07 17:32:51 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Sat Sep 06 19:18:34 2014 +0200
@@ -423,7 +423,6 @@
ordersave = new OB.DATA.OrderSave(this);
taxes = new OB.DATA.OrderTaxes(receipt);
- OB.POS.modelterminal.saveDocumentSequenceInDB();
this.processChangedCustomers();
this.processChangedCustomerAddress();
# HG changeset patch
# User Miguel de Juana <miguel.dejuana@openbravo.com>
# Date 1411471688 -7200
# Tue Sep 23 13:28:08 2014 +0200
# Node ID 66c542692433ba7b535fb750d5b20e071cecb76b
# Parent cfe16f6aae3ebd800bc3c05886a8169b1c92437b
Fixed issue 0027631: Document sequence is not reseted when you change the prefix
diff -r cfe16f6aae3e -r 66c542692433 src/org/openbravo/retail/posterminal/POSUtils.java
--- a/src/org/openbravo/retail/posterminal/POSUtils.java Sat Sep 06 19:18:34 2014 +0200
+++ b/src/org/openbravo/retail/posterminal/POSUtils.java Tue Sep 23 13:28:08 2014 +0200
@@ -324,13 +324,90 @@
query.setString(0, searchKey);
query.setString(1, searchKey);
int maxDocNo;
- List result = query.list();
- if (result.size() == 0 || result.get(0) == null) {
+ Object result = query.uniqueResult();
+ if (result == null) {
maxDocNo = 0;
} else if (curDbms.equals("POSTGRE")) {
- maxDocNo = ((BigDecimal) result.get(0)).intValue();
+ maxDocNo = ((BigDecimal) result).intValue();
} else if (curDbms.equals("ORACLE")) {
- maxDocNo = ((Long) result.get(0)).intValue();
+ maxDocNo = ((Long) result).intValue();
+ } else {
+ maxDocNo = 0;
+ }
+
+ // This number will be compared against the maximum number of the failed orders
+ OBCriteria<OBPOSErrors> errorCrit = OBDal.getInstance().createCriteria(OBPOSErrors.class);
+ errorCrit.add(Restrictions.eq(OBPOSErrors.PROPERTY_OBPOSAPPLICATIONS, terminal));
+ errorCrit.add(Restrictions.eq(OBPOSErrors.PROPERTY_TYPEOFDATA, "order"));
+ List<OBPOSErrors> errors = errorCrit.list();
+ for (OBPOSErrors error : errors) {
+ try {
+ JSONObject jsonError = new JSONObject(error.getJsoninfo());
+ if (jsonError.has("documentNo")) {
+ String documentNo = jsonError.getString("documentNo");
+ if (documentNo.indexOf("/") != 0) {
+ String number = documentNo.substring(documentNo.indexOf("/") + 1);
+ int errorNumber = new Long(number).intValue();
+ if (errorNumber > maxDocNo) {
+ maxDocNo = errorNumber;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // If not parseable, we continue
+ }
+ }
+ return maxDocNo;
+ }
+
+ public static int getLastDocumentNumberQuotationForPOS(String searchKey,
+ List<String> documentTypeIds) {
+ OBCriteria<OBPOSApplications> termCrit = OBDal.getInstance().createCriteria(
+ OBPOSApplications.class);
+ termCrit.add(Restrictions.eq(OBPOSApplications.PROPERTY_SEARCHKEY, searchKey));
+ if (termCrit.count() != 1) {
+ throw new OBException("Error while loading the terminal " + searchKey);
+ }
+ OBPOSApplications terminal = (OBPOSApplications) termCrit.uniqueResult();
+
+ String curDbms = OBPropertiesProvider.getInstance().getOpenbravoProperties()
+ .getProperty("bbdd.rdbms");
+ String sqlToExecute;
+ String doctypeIds = "";
+ for (String doctypeId : documentTypeIds) {
+ if (!doctypeIds.equals("")) {
+ doctypeIds += ",";
+ }
+ doctypeIds += "'" + doctypeId + "'";
+ }
+
+ if (curDbms.equals("POSTGRE")) {
+ sqlToExecute = "select max(a.docno) from (select to_number(substring(documentno, '/([0-9]+)$')) docno from c_order where em_obpos_applications_id= (select obpos_applications_id from obpos_applications where value = ?) and c_doctype_id in ("
+ + doctypeIds
+ + ") and documentno like (select quotationdocno_prefix from obpos_applications where value = ?)||'%') a";
+ } else if (curDbms.equals("ORACLE")) {
+ sqlToExecute = "select max(a.docno) from (select to_number(substr(REGEXP_SUBSTR(documentno, '/([0-9]+)$'), 2)) docno from c_order where em_obpos_applications_id= (select obpos_applications_id from obpos_applications where value = ?) and c_doctype_id in ("
+ + doctypeIds
+ + ") and documentno like (select quotationdocno_prefix from obpos_applications where value = ?)||'%' ) a";
+ } else {
+ // unknow DBMS
+ // shouldn't happen
+ log.error("Error getting max documentNo because the DBMS is unknown.");
+ return 0;
+ }
+
+ SQLQuery query = OBDal.getInstance().getSession().createSQLQuery(sqlToExecute);
+ query.setString(0, searchKey);
+ query.setString(1, searchKey);
+ int maxDocNo;
+ Object result = query.uniqueResult();
+ if (result == null) {
+ maxDocNo = 0;
+ } else if (curDbms.equals("POSTGRE")) {
+ maxDocNo = ((BigDecimal) result).intValue();
+ } else if (curDbms.equals("ORACLE")) {
+ maxDocNo = ((Long) result).intValue();
} else {
maxDocNo = 0;
}
@@ -368,6 +445,12 @@
}
+ public static int getLastDocumentNumberQuotationForPOS(String searchKey, String documentTypeId) {
+ ArrayList<String> doctypeId = new ArrayList<String>();
+ doctypeId.add(documentTypeId);
+ return getLastDocumentNumberQuotationForPOS(searchKey, doctypeId);
+ }
+
public static void getRetailDependantModules(Module module, List<Module> moduleList,
List<ModuleDependency> list) {
for (ModuleDependency depModule : list) {
diff -r cfe16f6aae3e -r 66c542692433 src/org/openbravo/retail/posterminal/term/Terminal.java
--- a/src/org/openbravo/retail/posterminal/term/Terminal.java Sat Sep 06 19:18:34 2014 +0200
+++ b/src/org/openbravo/retail/posterminal/term/Terminal.java Tue Sep 23 13:28:08 2014 +0200
@@ -62,7 +62,7 @@
doctypeIds);
int lastQuotationDocumentNumber = 0;
if (quotationsDocTypeId != null) {
- lastQuotationDocumentNumber = POSUtils.getLastDocumentNumberForPOS(
+ lastQuotationDocumentNumber = POSUtils.getLastDocumentNumberQuotationForPOS(
pOSTerminal.getSearchKey(), quotationsDocTypeId);
}
String warehouseId = POSUtils.getWarehouseForTerminal(pOSTerminal).getId();
diff -r cfe16f6aae3e -r 66c542692433 web/org.openbravo.retail.posterminal/js/login/model/login-model.js
--- a/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Sat Sep 06 19:18:34 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Tue Sep 23 13:28:08 2014 +0200
@@ -466,6 +466,13 @@
*/
saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix) {
var me = this;
+ if (me.restartingDocNo === true) {
+ return;
+ }
+ //If documentnoSuffix === 0 || quotationnoSuffix === 0, it means that we have restarted documentNo prefix, so we block this method while we save the new documentNo in localStorage
+ if (documentnoSuffix === 0 || quotationnoSuffix === 0) {
+ me.restartingDocNo = true;
+ }
/**
* If for whatever reason the maxSuffix is not the current order suffix (most likely, the server returning a higher docno value)
@@ -478,7 +485,7 @@
var orderlist = OB.MobileApp.model.orderList;
if (orderlist && orderlist.models.length > 0 && orderlist.current) {
if (orderlist.current.get('lines') && orderlist.current.get('lines').length === 0) {
- if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold) {
+ if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold || me.documentnoThreshold === 0) {
orderlist.deleteCurrent();
}
}
@@ -486,10 +493,10 @@
};
// verify that the values are higher than the local variables
- if (documentnoSuffix > this.documentnoThreshold) {
+ if (documentnoSuffix > this.documentnoThreshold || documentnoSuffix === 0) {
this.documentnoThreshold = documentnoSuffix;
}
- if (quotationnoSuffix > this.quotationnoThreshold) {
+ if (quotationnoSuffix > this.quotationnoThreshold || quotationnoSuffix === 0) {
this.quotationnoThreshold = quotationnoSuffix;
}
@@ -502,11 +509,11 @@
if (documentSequenceList && documentSequenceList.length > 0) {
// There can only be one documentSequence model in the list (posSearchKey is unique)
docSeq = documentSequenceList.models[0];
- // verify if the new values are higher
- if (docSeq.get('documentSequence') > me.documentnoThreshold) {
+ // verify if the new values are higher and if it is not undefined or 0
+ if (docSeq.get('documentSequence') > me.documentnoThreshold && documentnoSuffix !== 0) {
me.documentnoThreshold = docSeq.get('documentSequence');
}
- if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold) {
+ if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold && quotationnoSuffix !== 0) {
me.quotationnoThreshold = docSeq.get('quotationDocumentSequence');
}
} else {
@@ -520,12 +527,14 @@
docSeq.set('quotationDocumentSequence', me.quotationnoThreshold);
OB.Dal.save(docSeq, function () {
synchronizeCurrentOrder();
+ me.restartingDocNo = false;
}, function () {
// nothing to do
+ me.restartingDocNo = false;
});
}, function () {
- OB.debug("The 'c_document_sequence' table is locked");
+ me.restartingDocNo = false;
});
},
@@ -547,7 +556,7 @@
var i = OB.MobileApp.model.orderList.models.length - 1;
while (lastSuffix === null && i >= 0) {
var order = OB.MobileApp.model.orderList.models[i];
- if (!order.get('isPaid') && !order.get('isQuotation')) {
+ if (!order.get('isPaid') && !order.get('isQuotation') && order.get('docNoPrefix') === OB.MobileApp.model.get('terminal').docNoPrefix) {
lastSuffix = order.get('documentnoSuffix');
}
i--;
@@ -565,7 +574,7 @@
var i = OB.MobileApp.model.orderList.models.length - 1;
while (lastSuffix === null && i >= 0) {
var order = OB.MobileApp.model.orderList.models[i];
- if (order.get('isQuotation')) {
+ if (order.get('isQuotation') && order.get('quotationDocNoPrefix') === OB.MobileApp.model.get('terminal').quotationDocNoPrefix) {
lastSuffix = order.get('quotationnoSuffix');
}
i--;
diff -r cfe16f6aae3e -r 66c542692433 web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js Sat Sep 06 19:18:34 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js Tue Sep 23 13:28:08 2014 +0200
@@ -267,6 +267,8 @@
this.set('posTerminal', attributes.posTerminal);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, attributes['posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER]);
this.set('orderDate', new Date(attributes.orderDate));
+ this.set('quotationDocNoPrefix', attributes.quotationDocNoPrefix);
+ this.set('docNoPrefix', attributes.docNoPrefix);
this.set('documentnoSuffix', attributes.documentnoSuffix);
this.set('quotationnoSuffix', attributes.quotationnoSuffix);
this.set('documentNo', attributes.documentNo);
@@ -584,6 +586,8 @@
this.set('posTerminal', null);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, null);
this.set('orderDate', new Date());
+ this.set('quotationDocNoPrefix', -1);
+ this.set('docNoPrefix', -1);
this.set('documentnoSuffix', -1);
this.set('quotationnoSuffix', -1);
this.set('documentNo', '');
@@ -1377,9 +1381,11 @@
this.set('isPaid', false);
this.set('isEditable', true);
this.set('orderDate', new Date());
+ this.set('quotationDocNoPrefix', OB.MobileApp.model.get('terminal').quotationDocNoPrefix);
+ this.set('docNoPrefix', OB.MobileApp.model.get('terminal').docNoPrefix);
var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
this.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
- this.set('documentNo', nextDocumentno.documentNo);
+ this.set('documentNo', nextDocumentno.documentNo);
this.set('posTerminal', OB.POS.modelterminal.get('terminal').id);
this.save();
if (updatePrices) {
@@ -1684,9 +1690,11 @@
order.set('isLayaway', false);
order.set('taxes', null);
+ order.set('quotationDocNoPrefix', OB.MobileApp.model.get('terminal').quotationDocNoPrefix);
+ order.set('docNoPrefix', OB.MobileApp.model.get('terminal').docNoPrefix);
var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
order.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
- order.set('documentNo', nextDocumentno.documentNo);
+ order.set('documentNo', nextDocumentno.documentNo);
order.set('bp', OB.POS.modelterminal.get('businessPartner'));
order.set('print', true);
@@ -1887,7 +1895,7 @@
this.current.set('documentType', OB.POS.modelterminal.get('terminal').terminalType.documentTypeForQuotations);
var nextQuotationno = OB.MobileApp.model.getNextQuotationno();
this.current.set('quotationnoSuffix', nextQuotationno.quotationnoSuffix);
- this.current.set('documentNo', nextQuotationno.documentNo);
+ this.current.set('documentNo', nextQuotationno.documentNo);
this.add(this.current);
this.loadCurrent();
# HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1412946866 -7200
# Fri Oct 10 15:14:26 2014 +0200
# Node ID 06292de08888bedcf18ab13861e0c1572515dc79
# Parent 87f76bd8048aa9cd3ec268618696a5a6c4727493
Fixes issue 27548: OB.MobileApp.model.orderList points to the order list and their methods
diff -r 87f76bd8048a -r 06292de08888 web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Tue Oct 07 00:11:26 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Fri Oct 10 15:14:26 2014 +0200
@@ -239,6 +239,7 @@
});
this.set('order', receipt);
orderList = new OB.Collection.OrderList(receipt);
+ OB.MobileApp.model.orderList = orderList;
this.set('orderList', orderList);
this.set('customer', new OB.Model.BusinessPartner());
this.set('customerAddr', new OB.Model.BPLocation());
# HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1412947434 -7200
# Fri Oct 10 15:23:54 2014 +0200
# Node ID d742e2eed52cfc844be93dac4c1817aa3bdf446c
# Parent 06292de08888bedcf18ab13861e0c1572515dc79
Fixes issue 27309 and issue 27476: A new document sequence algorithm has been introduced to preserve consecutive document numbers
This logic:
- can handle the regular activity with the WebPOS: navigating, adding, deleting, changing orders, etc.
- it does not fill gaps that the user do not want to. e.g: if order 001 is paid, then 3 empty orders are created and then the 004 is paid; 005 will be the next valid document number
- synchronizes the document number with the server each time the terminal info is updated, which is, as of now, after login, every page refresh and every x minutes
- cannot handle 2 or more terminals with the same id, running at the same time
diff -r 06292de08888 -r d742e2eed52c web/org.openbravo.retail.posterminal/js/data/dataordersave.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordersave.js Fri Oct 10 15:14:26 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordersave.js Fri Oct 10 15:23:54 2014 +0200
@@ -37,7 +37,8 @@
}
this.receipt.set('hasbeenpaid', 'Y');
- OB.UTIL.updateDocumentSequenceInDB(docno);
+ OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(this.receipt.get('documentnoSuffix'), this.receipt.get('quotationnoSuffix'));
+
delete this.receipt.attributes.json;
this.receipt.set('timezoneOffset', creationDate.getTimezoneOffset());
@@ -172,7 +173,7 @@
this.receipt.set('hasbeenpaid', 'Y');
- OB.UTIL.updateDocumentSequenceInDB(docno);
+ OB.MobileApp.model.updateDocumentSequenceWhenOrderSaved(this.receipt.get('documentnoSuffix'), this.receipt.get('quotationnoSuffix'));
delete this.receipt.attributes.json;
this.receipt.set('timezoneOffset', creationDate.getTimezoneOffset());
diff -r 06292de08888 -r d742e2eed52c web/org.openbravo.retail.posterminal/js/login/model/login-model.js
--- a/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Fri Oct 10 15:14:26 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Fri Oct 10 15:23:54 2014 +0200
@@ -114,7 +114,12 @@
});
}
} else if (data[0]) {
+ // load the OB.MobileApp.model.get('terminal') attributes
terminalModel.set(me.properties[0], data[0]);
+
+ // update the local database with the document sequence received
+ OB.MobileApp.model.saveDocumentSequence(OB.MobileApp.model.get('terminal').lastDocumentNumber, OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber);
+
window.localStorage.setItem('terminalId', data[0].id);
terminalModel.set('useBarcode', terminalModel.get('terminal').terminalType.usebarcodescanner);
OB.MobileApp.view.scanningFocus(true);
@@ -513,11 +518,10 @@
});
- this.on('seqNoReady', function () {
- this.trigger('ready'); //NAVIGATE
- }, this);
+ // force the initialization of the document sequence info
+ this.saveDocumentSequence();
- this.setDocumentSequence();
+ this.trigger('ready');
},
postLoginActions: function () {
@@ -595,136 +599,145 @@
});
},
- compareDocSeqWithPendingOrdersAndSave: function (maxDocumentSequence, maxQuotationDocumentSequence) {
- var orderDocNo, quotationDocNo;
- // compare the last document number returned from the ERP with
- // the last document number of the unprocessed pending lines (if any)
- OB.Dal.find(OB.Model.Order, {}, function (fetchedOrderList) {
- var criteria, maxDocumentSequencePendingOrders;
- if (!fetchedOrderList || fetchedOrderList.length === 0) {
- // There are no pending orders, the initial document sequence
- // will be the one fetched from the database
- OB.MobileApp.model.saveDocumentSequenceAndGo(maxDocumentSequence, maxQuotationDocumentSequence);
- } else {
- // There are pending orders. The document sequence will be set
- // to the maximum of the pending order document sequence and the
- // document sequence retrieved from the server
- maxDocumentSequencePendingOrders = OB.MobileApp.model.getMaxDocumentSequenceFromPendingOrders(fetchedOrderList.models);
- if (maxDocumentSequencePendingOrders.orderDocNo > maxDocumentSequence) {
- orderDocNo = maxDocumentSequencePendingOrders.orderDocNo;
- } else {
- orderDocNo = maxDocumentSequence;
+ // these variables will keep the minimum value that the document order could have
+ // they feed from the local database, and the server
+ documentnoThreshold: -1,
+ quotationnoThreshold: -1,
+
+ /**
+ * Save the new values if are higher than the last knowwn values
+ * - the minimum sequence number can only grow
+ */
+ saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix) {
+ var me = this;
+
+ /**
+ * If for whatever reason the maxSuffix is not the current order suffix (most likely, the server returning a higher docno value)
+ * 1. if there is a current order
+ * 2. and has no lines (no product added, etc)
+ * 3. if the current order suffix is lower than the minNumbers
+ * 4. delete the order
+ */
+ var synchronizeCurrentOrder = function () {
+ var orderlist = OB.MobileApp.model.orderList;
+ if (orderlist && orderlist.models.length > 0 && orderlist.current) {
+ if (orderlist.current.get('lines') && orderlist.current.get('lines').length === 0) {
+ if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold) {
+ orderlist.deleteCurrent();
+ }
+ }
}
- if (maxDocumentSequencePendingOrders.quotationDocNo > maxQuotationDocumentSequence) {
- quotationDocNo = maxDocumentSequencePendingOrders.quotationDocNo;
- } else {
- quotationDocNo = maxQuotationDocumentSequence;
- }
- OB.MobileApp.model.saveDocumentSequenceAndGo(orderDocNo, quotationDocNo);
- }
- }, function () {
- // If c_order does not exist yet, go with the sequence
- // number fetched from the server
- OB.MobileApp.model.saveDocumentSequenceAndGo(maxDocumentSequence, maxQuotationDocumentSequence);
- });
- },
+ };
- getMaxDocumentSequenceFromPendingOrders: function (pendingOrders) {
- var nPreviousOrders = pendingOrders.length,
- maxDocumentSequence = OB.MobileApp.model.get('terminal').lastDocumentNumber,
- maxQuotationDocumentSequence = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber,
- orderCompleteDocumentNo, orderDocumentSequence, i;
- for (i = 0; i < nPreviousOrders; i++) {
- orderCompleteDocumentNo = pendingOrders[i].get('documentNo');
- if (!pendingOrders[i].get('isQuotation')) {
- orderDocumentSequence = OB.UTIL.getNumberOfSequence(pendingOrders[i].get('documentNo'), false);
- if (orderDocumentSequence > maxDocumentSequence) {
- maxDocumentSequence = orderDocumentSequence;
- }
- } else {
- orderDocumentSequence = OB.UTIL.getNumberOfSequence(pendingOrders[i].get('documentNo'), true);
- if (orderDocumentSequence > maxQuotationDocumentSequence) {
- maxQuotationDocumentSequence = orderDocumentSequence;
- }
- }
+ // verify that the values are higher than the local variables
+ if (documentnoSuffix > this.documentnoThreshold) {
+ this.documentnoThreshold = documentnoSuffix;
}
- return {
- orderDocNo: maxDocumentSequence,
- quotationDocNo: maxQuotationDocumentSequence
- };
- },
+ if (quotationnoSuffix > this.quotationnoThreshold) {
+ this.quotationnoThreshold = quotationnoSuffix;
+ }
- saveDocumentSequenceAndGo: function (documentSequence, quotationDocumentSequence) {
- this.set('documentsequence', documentSequence);
- this.set('quotationDocumentSequence', quotationDocumentSequence);
- this.trigger('seqNoReady');
- },
+ // verify the database values
+ OB.Dal.find(OB.Model.DocumentSequence, {
+ 'posSearchKey': this.get('terminal').searchKey
+ }, function (documentSequenceList) {
- setDocumentSequence: function () {
- // Obtains the persisted document number (documentno of the last processed order)
- OB.Dal.find(OB.Model.DocumentSequence, {
- 'posSearchKey': OB.MobileApp.model.terminalName
- }, function (documentsequence) {
- var lastInternalDocumentSequence, lastInternalQuotationSequence, max, maxquote;
- if (documentsequence && documentsequence.length > 0) {
- lastInternalDocumentSequence = documentsequence.at(0).get('documentSequence');
- lastInternalQuotationSequence = documentsequence.at(0).get('quotationDocumentSequence');
- // Compares the persisted document number with the fetched from the server
- if (lastInternalDocumentSequence > OB.MobileApp.model.get('terminal').lastDocumentNumber) {
- max = lastInternalDocumentSequence;
- } else {
- max = OB.MobileApp.model.get('terminal').lastDocumentNumber;
- }
- if (lastInternalQuotationSequence > OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber) {
- maxquote = lastInternalQuotationSequence;
- } else {
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- }
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- } else {
- max = OB.MobileApp.model.get('terminal').lastDocumentNumber;
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- }
-
- }, function () {
- var max = OB.MobileApp.model.get('terminal').lastDocumentNumber,
- maxquote = OB.MobileApp.model.get('terminal').lastQuotationDocumentNumber;
- // Compares the maximum with the document number of the paid pending orders
- OB.MobileApp.model.compareDocSeqWithPendingOrdersAndSave(max, maxquote);
- });
- },
-
- saveDocumentSequenceInDB: function () {
- var me = this,
- documentSequence = this.get('documentsequence'),
- quotationDocumentSequence = this.get('quotationDocumentSequence'),
- criteria = {
- 'posSearchKey': this.get('terminal').searchKey
- };
- OB.Dal.find(OB.Model.DocumentSequence, criteria, function (documentSequenceList) {
var docSeq;
- if (documentSequenceList && documentSequenceList.length !== 0) {
+ if (documentSequenceList && documentSequenceList.length > 0) {
// There can only be one documentSequence model in the list (posSearchKey is unique)
docSeq = documentSequenceList.models[0];
- // There exists already a document sequence, update it
- docSeq.set('documentSequence', documentSequence);
- docSeq.set('quotationDocumentSequence', quotationDocumentSequence);
+ // verify if the new values are higher
+ if (docSeq.get('documentSequence') > me.documentnoThreshold) {
+ me.documentnoThreshold = docSeq.get('documentSequence');
+ }
+ if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold) {
+ me.quotationnoThreshold = docSeq.get('quotationDocumentSequence');
+ }
} else {
// There is not a document sequence for the pos, create it
docSeq = new OB.Model.DocumentSequence();
docSeq.set('posSearchKey', me.get('terminal').searchKey);
- docSeq.set('documentSequence', documentSequence);
- docSeq.set('quotationDocumentSequence', quotationDocumentSequence);
}
- OB.Dal.save(docSeq, null, function () {
- OB.error(arguments);
+
+ // update the database
+ docSeq.set('documentSequence', me.documentnoThreshold);
+ docSeq.set('quotationDocumentSequence', me.quotationnoThreshold);
+ OB.Dal.save(docSeq, function () {
+ synchronizeCurrentOrder();
+ }, function () {
+ // nothing to do
});
+
+ }, function () {
+ OB.debug("The 'c_document_sequence' table is locked");
});
},
+ /**
+ * 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) {
+ if (quotationnoSuffix >= 0) {
+ documentnoSuffix = -1;
+ }
+ this.saveDocumentSequence(documentnoSuffix, quotationnoSuffix);
+ },
+
+ // get the first document number available
+ getLastDocumentnoSuffixInOrderlist: function () {
+ var lastSuffix = null;
+ if (OB.MobileApp.model.orderList.length > 0) {
+ var i = OB.MobileApp.model.orderList.models.length - 1;
+ while (lastSuffix === null && i >= 0) {
+ var order = OB.MobileApp.model.orderList.models[i];
+ if (!order.get('isPaid') && !order.get('isQuotation')) {
+ lastSuffix = order.get('documentnoSuffix');
+ }
+ i--;
+ }
+ }
+ if (lastSuffix === null || lastSuffix < this.documentnoThreshold) {
+ lastSuffix = this.documentnoThreshold;
+ }
+ return lastSuffix;
+ },
+ // get the first quotation number available
+ getLastQuotationnoSuffixInOrderlist: function () {
+ var lastSuffix = null;
+ if (OB.MobileApp.model.orderList.length > 0) {
+ var i = OB.MobileApp.model.orderList.models.length - 1;
+ while (lastSuffix === null && i >= 0) {
+ var order = OB.MobileApp.model.orderList.models[i];
+ if (order.get('isQuotation')) {
+ lastSuffix = order.get('quotationnoSuffix');
+ }
+ i--;
+ }
+ }
+ if (lastSuffix === null || lastSuffix < this.quotationnoThreshold) {
+ lastSuffix = this.quotationnoThreshold;
+ }
+ return lastSuffix;
+ },
+
+ // call this method to get a new order document number
+ getNextDocumentno: function () {
+ var next = this.getLastDocumentnoSuffixInOrderlist() + 1;
+ return {
+ documentnoSuffix: next,
+ documentNo: OB.MobileApp.model.get('terminal').docNoPrefix + '/' + OB.UTIL.padNumber(next, 7)
+ };
+ },
+ // call this method to get a new quotation document number
+ getNextQuotationno: function () {
+ var next = this.getLastQuotationnoSuffixInOrderlist() + 1;
+ return {
+ quotationnoSuffix: next,
+ documentNo: OB.MobileApp.model.get('terminal').quotationDocNoPrefix + '/' + OB.UTIL.padNumber(next, 7)
+ };
+ },
+
getPaymentName: function (key) {
if (this.paymentnames[key] && this.paymentnames[key].payment && this.paymentnames[key].payment._identifier) {
return this.paymentnames[key].payment._identifier;
diff -r 06292de08888 -r d742e2eed52c web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js Fri Oct 10 15:14:26 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js Fri Oct 10 15:23:54 2014 +0200
@@ -267,6 +267,8 @@
this.set('posTerminal', attributes.posTerminal);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, attributes['posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER]);
this.set('orderDate', new Date(attributes.orderDate));
+ this.set('documentnoSuffix', attributes.documentnoSuffix);
+ this.set('quotationnoSuffix', attributes.quotationnoSuffix);
this.set('documentNo', attributes.documentNo);
this.set('undo', attributes.undo);
this.set('bp', new Backbone.Model(attributes.bp));
@@ -578,6 +580,8 @@
this.set('posTerminal', null);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, null);
this.set('orderDate', new Date());
+ this.set('documentnoSuffix', -1);
+ this.set('quotationnoSuffix', -1);
this.set('documentNo', '');
this.set('undo', null);
this.set('bp', null);
@@ -1376,10 +1380,9 @@
this.set('isPaid', false);
this.set('isEditable', true);
this.set('orderDate', new Date());
- documentseq = OB.POS.modelterminal.get('documentsequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('documentsequence', documentseq);
- this.set('documentNo', OB.POS.modelterminal.get('terminal').docNoPrefix + '/' + documentseqstr);
+ var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
+ this.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
+ this.set('documentNo', nextDocumentno.documentNo);
this.set('posTerminal', OB.POS.modelterminal.get('terminal').id);
this.save();
if (updatePrices) {
@@ -2075,10 +2078,9 @@
order.set('isLayaway', false);
order.set('taxes', null);
- documentseq = OB.POS.modelterminal.get('documentsequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('documentsequence', documentseq);
- order.set('documentNo', OB.POS.modelterminal.get('terminal').docNoPrefix + '/' + documentseqstr);
+ var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
+ order.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
+ order.set('documentNo', nextDocumentno.documentNo);
order.set('bp', OB.POS.modelterminal.get('businessPartner'));
order.set('print', true);
@@ -2277,10 +2279,10 @@
this.current.set('isQuotation', true);
this.current.set('generateInvoice', false);
this.current.set('documentType', OB.POS.modelterminal.get('terminal').terminalType.documentTypeForQuotations);
- documentseq = OB.POS.modelterminal.get('quotationDocumentSequence') + 1;
- documentseqstr = OB.UTIL.padNumber(documentseq, 7);
- OB.POS.modelterminal.set('quotationDocumentSequence', documentseq);
- this.current.set('documentNo', OB.POS.modelterminal.get('terminal').quotationDocNoPrefix + '/' + documentseqstr);
+ var nextQuotationno = OB.MobileApp.model.getNextQuotationno();
+ this.current.set('quotationnoSuffix', nextQuotationno.quotationnoSuffix);
+ this.current.set('documentNo', nextQuotationno.documentNo);
+
this.add(this.current);
this.loadCurrent();
},
# HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1412948683 -7200
# Fri Oct 10 15:44:43 2014 +0200
# Node ID 0cc9a2a7002727f4ae51d6c43dde4614a37d6694
# Parent d742e2eed52cfc844be93dac4c1817aa3bdf446c
Fixes issue 27631: Document sequence is not reseted when you change the prefix
diff -r d742e2eed52c -r 0cc9a2a70027 src/org/openbravo/retail/posterminal/POSUtils.java
--- a/src/org/openbravo/retail/posterminal/POSUtils.java Fri Oct 10 15:23:54 2014 +0200
+++ b/src/org/openbravo/retail/posterminal/POSUtils.java Fri Oct 10 15:44:43 2014 +0200
@@ -371,6 +371,83 @@
return maxDocNo;
}
+ public static int getLastDocumentNumberQuotationForPOS(String searchKey,
+ List<String> documentTypeIds) {
+ OBCriteria<OBPOSApplications> termCrit = OBDal.getInstance().createCriteria(
+ OBPOSApplications.class);
+ termCrit.add(Restrictions.eq(OBPOSApplications.PROPERTY_SEARCHKEY, searchKey));
+ if (termCrit.count() != 1) {
+ throw new OBException("Error while loading the terminal " + searchKey);
+ }
+ OBPOSApplications terminal = (OBPOSApplications) termCrit.uniqueResult();
+
+ String curDbms = OBPropertiesProvider.getInstance().getOpenbravoProperties()
+ .getProperty("bbdd.rdbms");
+ String sqlToExecute;
+ String doctypeIds = "";
+ for (String doctypeId : documentTypeIds) {
+ if (!doctypeIds.equals("")) {
+ doctypeIds += ",";
+ }
+ doctypeIds += "'" + doctypeId + "'";
+ }
+
+ if (curDbms.equals("POSTGRE")) {
+ sqlToExecute = "select max(a.docno) from (select to_number(substring(documentno, '/([0-9]+)$')) docno from c_order where em_obpos_applications_id= (select obpos_applications_id from obpos_applications where value = ?) and c_doctype_id in ("
+ + doctypeIds
+ + ") and documentno like (select quotationdocno_prefix from obpos_applications where value = ?)||'%') a";
+ } else if (curDbms.equals("ORACLE")) {
+ sqlToExecute = "select max(a.docno) from (select to_number(substr(REGEXP_SUBSTR(documentno, '/([0-9]+)$'), 2)) docno from c_order where em_obpos_applications_id= (select obpos_applications_id from obpos_applications where value = ?) and c_doctype_id in ("
+ + doctypeIds
+ + ") and documentno like (select quotationdocno_prefix from obpos_applications where value = ?)||'%' ) a";
+ } else {
+ // unknow DBMS
+ // shouldn't happen
+ log.error("Error getting max documentNo because the DBMS is unknown.");
+ return 0;
+ }
+
+ SQLQuery query = OBDal.getInstance().getSession().createSQLQuery(sqlToExecute);
+ query.setString(0, searchKey);
+ query.setString(1, searchKey);
+ int maxDocNo;
+ Object result = query.uniqueResult();
+ if (result == null) {
+ maxDocNo = 0;
+ } else if (curDbms.equals("POSTGRE")) {
+ maxDocNo = ((BigDecimal) result).intValue();
+ } else if (curDbms.equals("ORACLE")) {
+ maxDocNo = ((Long) result).intValue();
+ } else {
+ maxDocNo = 0;
+ }
+
+ // This number will be compared against the maximum number of the failed orders
+ OBCriteria<OBPOSErrors> errorCrit = OBDal.getInstance().createCriteria(OBPOSErrors.class);
+ errorCrit.add(Restrictions.eq(OBPOSErrors.PROPERTY_OBPOSAPPLICATIONS, terminal));
+ errorCrit.add(Restrictions.eq(OBPOSErrors.PROPERTY_TYPEOFDATA, "order"));
+ List<OBPOSErrors> errors = errorCrit.list();
+ for (OBPOSErrors error : errors) {
+ try {
+ JSONObject jsonError = new JSONObject(error.getJsoninfo());
+ if (jsonError.has("documentNo")) {
+ String documentNo = jsonError.getString("documentNo");
+ if (documentNo.indexOf("/") != 0) {
+ String number = documentNo.substring(documentNo.indexOf("/") + 1);
+ int errorNumber = new Long(number).intValue();
+ if (errorNumber > maxDocNo) {
+ maxDocNo = errorNumber;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // If not parseable, we continue
+ }
+ }
+ return maxDocNo;
+ }
+
public static int getLastDocumentNumberForPOS(String searchKey, String documentTypeId) {
ArrayList<String> doctypeId = new ArrayList<String>();
doctypeId.add(documentTypeId);
@@ -378,6 +455,12 @@
}
+ public static int getLastDocumentNumberQuotationForPOS(String searchKey, String documentTypeId) {
+ ArrayList<String> doctypeId = new ArrayList<String>();
+ doctypeId.add(documentTypeId);
+ return getLastDocumentNumberQuotationForPOS(searchKey, doctypeId);
+ }
+
public static void getRetailDependantModules(Module module, List<Module> moduleList,
List<ModuleDependency> list) {
for (ModuleDependency depModule : list) {
diff -r d742e2eed52c -r 0cc9a2a70027 src/org/openbravo/retail/posterminal/term/Terminal.java
--- a/src/org/openbravo/retail/posterminal/term/Terminal.java Fri Oct 10 15:23:54 2014 +0200
+++ b/src/org/openbravo/retail/posterminal/term/Terminal.java Fri Oct 10 15:44:43 2014 +0200
@@ -62,7 +62,7 @@
doctypeIds);
int lastQuotationDocumentNumber = 0;
if (quotationsDocTypeId != null) {
- lastQuotationDocumentNumber = POSUtils.getLastDocumentNumberForPOS(
+ lastQuotationDocumentNumber = POSUtils.getLastDocumentNumberQuotationForPOS(
pOSTerminal.getSearchKey(), quotationsDocTypeId);
}
String warehouseId = POSUtils.getWarehouseForTerminal(pOSTerminal).getId();
diff -r d742e2eed52c -r 0cc9a2a70027 web/org.openbravo.retail.posterminal/js/login/model/login-model.js
--- a/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Fri Oct 10 15:23:54 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/login/model/login-model.js Fri Oct 10 15:44:43 2014 +0200
@@ -610,6 +610,13 @@
*/
saveDocumentSequence: function (documentnoSuffix, quotationnoSuffix) {
var me = this;
+ if (me.restartingDocNo === true) {
+ return;
+ }
+ //If documentnoSuffix === 0 || quotationnoSuffix === 0, it means that we have restarted documentNo prefix, so we block this method while we save the new documentNo in localStorage
+ if (documentnoSuffix === 0 || quotationnoSuffix === 0) {
+ me.restartingDocNo = true;
+ }
/**
* If for whatever reason the maxSuffix is not the current order suffix (most likely, the server returning a higher docno value)
@@ -622,7 +629,7 @@
var orderlist = OB.MobileApp.model.orderList;
if (orderlist && orderlist.models.length > 0 && orderlist.current) {
if (orderlist.current.get('lines') && orderlist.current.get('lines').length === 0) {
- if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold) {
+ if (orderlist.current.get('documentnoSuffix') <= me.documentnoThreshold || me.documentnoThreshold === 0) {
orderlist.deleteCurrent();
}
}
@@ -630,10 +637,10 @@
};
// verify that the values are higher than the local variables
- if (documentnoSuffix > this.documentnoThreshold) {
+ if (documentnoSuffix > this.documentnoThreshold || documentnoSuffix === 0) {
this.documentnoThreshold = documentnoSuffix;
}
- if (quotationnoSuffix > this.quotationnoThreshold) {
+ if (quotationnoSuffix > this.quotationnoThreshold || quotationnoSuffix === 0) {
this.quotationnoThreshold = quotationnoSuffix;
}
@@ -646,11 +653,11 @@
if (documentSequenceList && documentSequenceList.length > 0) {
// There can only be one documentSequence model in the list (posSearchKey is unique)
docSeq = documentSequenceList.models[0];
- // verify if the new values are higher
- if (docSeq.get('documentSequence') > me.documentnoThreshold) {
+ // verify if the new values are higher and if it is not undefined or 0
+ if (docSeq.get('documentSequence') > me.documentnoThreshold && documentnoSuffix !== 0) {
me.documentnoThreshold = docSeq.get('documentSequence');
}
- if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold) {
+ if (docSeq.get('quotationDocumentSequence') > me.quotationnoThreshold && quotationnoSuffix !== 0) {
me.quotationnoThreshold = docSeq.get('quotationDocumentSequence');
}
} else {
@@ -664,12 +671,14 @@
docSeq.set('quotationDocumentSequence', me.quotationnoThreshold);
OB.Dal.save(docSeq, function () {
synchronizeCurrentOrder();
+ me.restartingDocNo = false;
}, function () {
// nothing to do
+ me.restartingDocNo = false;
});
}, function () {
- OB.debug("The 'c_document_sequence' table is locked");
+ me.restartingDocNo = false;
});
},
@@ -691,7 +700,7 @@
var i = OB.MobileApp.model.orderList.models.length - 1;
while (lastSuffix === null && i >= 0) {
var order = OB.MobileApp.model.orderList.models[i];
- if (!order.get('isPaid') && !order.get('isQuotation')) {
+ if (!order.get('isPaid') && !order.get('isQuotation') && order.get('docNoPrefix') === OB.MobileApp.model.get('terminal').docNoPrefix) {
lastSuffix = order.get('documentnoSuffix');
}
i--;
@@ -709,7 +718,7 @@
var i = OB.MobileApp.model.orderList.models.length - 1;
while (lastSuffix === null && i >= 0) {
var order = OB.MobileApp.model.orderList.models[i];
- if (order.get('isQuotation')) {
+ if (order.get('isQuotation') && order.get('quotationDocNoPrefix') === OB.MobileApp.model.get('terminal').quotationDocNoPrefix) {
lastSuffix = order.get('quotationnoSuffix');
}
i--;
diff -r d742e2eed52c -r 0cc9a2a70027 web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js Fri Oct 10 15:23:54 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js Fri Oct 10 15:44:43 2014 +0200
@@ -267,6 +267,8 @@
this.set('posTerminal', attributes.posTerminal);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, attributes['posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER]);
this.set('orderDate', new Date(attributes.orderDate));
+ this.set('quotationDocNoPrefix', attributes.quotationDocNoPrefix);
+ this.set('docNoPrefix', attributes.docNoPrefix);
this.set('documentnoSuffix', attributes.documentnoSuffix);
this.set('quotationnoSuffix', attributes.quotationnoSuffix);
this.set('documentNo', attributes.documentNo);
@@ -580,6 +582,8 @@
this.set('posTerminal', null);
this.set('posTerminal' + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER, null);
this.set('orderDate', new Date());
+ this.set('quotationDocNoPrefix', -1);
+ this.set('docNoPrefix', -1);
this.set('documentnoSuffix', -1);
this.set('quotationnoSuffix', -1);
this.set('documentNo', '');
@@ -1380,9 +1384,11 @@
this.set('isPaid', false);
this.set('isEditable', true);
this.set('orderDate', new Date());
+ this.set('quotationDocNoPrefix', OB.MobileApp.model.get('terminal').quotationDocNoPrefix);
+ this.set('docNoPrefix', OB.MobileApp.model.get('terminal').docNoPrefix);
var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
this.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
- this.set('documentNo', nextDocumentno.documentNo);
+ this.set('documentNo', nextDocumentno.documentNo);
this.set('posTerminal', OB.POS.modelterminal.get('terminal').id);
this.save();
if (updatePrices) {
@@ -2078,9 +2084,11 @@
order.set('isLayaway', false);
order.set('taxes', null);
+ order.set('quotationDocNoPrefix', OB.MobileApp.model.get('terminal').quotationDocNoPrefix);
+ order.set('docNoPrefix', OB.MobileApp.model.get('terminal').docNoPrefix);
var nextDocumentno = OB.MobileApp.model.getNextDocumentno();
order.set('documentnoSuffix', nextDocumentno.documentnoSuffix);
- order.set('documentNo', nextDocumentno.documentNo);
+ order.set('documentNo', nextDocumentno.documentNo);
order.set('bp', OB.POS.modelterminal.get('businessPartner'));
order.set('print', true);
@@ -2281,7 +2289,7 @@
this.current.set('documentType', OB.POS.modelterminal.get('terminal').terminalType.documentTypeForQuotations);
var nextQuotationno = OB.MobileApp.model.getNextQuotationno();
this.current.set('quotationnoSuffix', nextQuotationno.quotationnoSuffix);
- this.current.set('documentNo', nextQuotationno.documentNo);
+ this.current.set('documentNo', nextQuotationno.documentNo);
this.add(this.current);
this.loadCurrent();
# HG changeset patch
# User Rafa Alonso <rafael.alonso@openbravo.com>
# Date 1413284819 -7200
# Tue Oct 14 13:06:59 2014 +0200
# Node ID c27d797b43dc83c71d4e19f1b9a71eb3873da401
# Parent 92e8619558fb32f17ee702bcfcd523d5c0fd4b3c
Related to issue 27476: Missing change in previous documentno changesets
diff -r 92e8619558fb -r c27d797b43dc web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Wed Oct 08 12:05:34 2014 +0200
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/model/pointofsale-model.js Tue Oct 14 13:06:59 2014 +0200
@@ -372,7 +372,6 @@
ordersave = new OB.DATA.OrderSave(this);
taxes = new OB.DATA.OrderTaxes(receipt);
- OB.POS.modelterminal.saveDocumentSequenceInDB();
OB.MobileApp.model.runSyncProcess(function () {
me.loadCheckedMultiorders();
}, function () {
| |||||||
Relationships [ Relation Graph ]
[ Dependency Graph ]
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2014-10-09 13:05 | Orekaria | New Issue | |
| 2014-10-09 13:05 | Orekaria | Assigned To | => Orekaria |
| 2014-10-09 13:05 | Orekaria | OBNetwork customer | => No |
| 2014-10-09 13:05 | Orekaria | Triggers an Emergency Pack | => No |
| 2014-10-09 13:06 | Orekaria | Relationship added | depends on 0027631 |
| 2014-10-09 13:07 | Orekaria | Relationship added | depends on 0027476 |
| 2014-10-09 13:07 | Orekaria | Relationship added | depends on 0027548 |
| 2014-10-09 13:08 | Orekaria | File Added: 27548_Q2.4.patch | |
| 2014-10-09 13:08 | Orekaria | File Added: 27309_27476_Q2.4.patch | |
| 2014-10-09 13:09 | Orekaria | File Added: 27631_Q2.4.patch | |
| 2014-10-09 13:10 | Orekaria | Summary | Backport the document number fixes for Q4 to Q2.4/Q3 => Backport the document number fixes introduced in Q4 to Q2.4/Q3 |
| 2014-10-09 13:10 | Orekaria | Description Updated | View Revisions |
| 2014-10-09 13:12 | Orekaria | Status | new => scheduled |
| 2014-10-09 13:12 | Orekaria | fix_in_branch | => pi |
| 2014-10-09 13:12 | Orekaria | Status | scheduled => resolved |
| 2014-10-09 13:12 | Orekaria | Fixed in Version | => RR14Q2.3 |
| 2014-10-09 13:12 | Orekaria | Resolution | open => fixed |
| 2014-10-09 13:34 | Orekaria | Status | resolved => new |
| 2014-10-09 13:34 | Orekaria | Resolution | fixed => open |
| 2014-10-09 13:34 | Orekaria | Fixed in Version | RR14Q2.3 => |
| 2014-10-09 13:34 | Orekaria | Relationship added | depends on 0027309 |
| 2014-10-09 13:45 | Orekaria | fix_in_branch | pi => |
| 2014-10-09 13:45 | Orekaria | Description Updated | View Revisions |
| 2014-10-09 13:45 | Orekaria | Status | new => scheduled |
| 2014-10-09 13:45 | Orekaria | fix_in_branch | => pi |
| 2014-10-09 13:45 | Orekaria | Status | scheduled => resolved |
| 2014-10-09 13:45 | Orekaria | Fixed in Version | => RR14Q2.3 |
| 2014-10-09 13:45 | Orekaria | Resolution | open => fixed |
| 2014-10-14 09:11 | Orekaria | Status | resolved => new |
| 2014-10-14 09:11 | Orekaria | Resolution | fixed => open |
| 2014-10-14 09:11 | Orekaria | Fixed in Version | RR14Q2.3 => |
| 2014-10-14 09:12 | Orekaria | File Added: 27548_Q3.patch | |
| 2014-10-14 09:13 | Orekaria | File Added: 27309_27476_Q3.patch | |
| 2014-10-14 09:14 | Orekaria | File Added: 27631_Q3.patch | |
| 2014-10-14 09:14 | Orekaria | Status | new => feedback |
| 2014-10-14 13:09 | Orekaria | File Added: 27476_Q3_II.patch | |
| 2014-11-11 14:36 | Orekaria | Relationship added | blocks 0027911 |
| 2016-05-25 12:28 | Orekaria | Review Assigned To | => Orekaria |
| 2016-05-25 12:28 | Orekaria | Status | feedback => closed |
| 2016-05-25 12:28 | Orekaria | Resolution | open => no change required |
| Copyright © 2000 - 2009 MantisBT Group |

