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 () { | |||||||
![]() |
||||||||||||||||||||||||||||||||||||
|
![]() |
|||
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 |