summaryrefslogtreecommitdiff
path: root/addons/barcodes/static/src/js/barcode_parser.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/barcodes/static/src/js/barcode_parser.js')
-rw-r--r--addons/barcodes/static/src/js/barcode_parser.js248
1 files changed, 248 insertions, 0 deletions
diff --git a/addons/barcodes/static/src/js/barcode_parser.js b/addons/barcodes/static/src/js/barcode_parser.js
new file mode 100644
index 00000000000..e3b9ae3fd4e
--- /dev/null
+++ b/addons/barcodes/static/src/js/barcode_parser.js
@@ -0,0 +1,248 @@
+function openerp_barcode_parser(instance,module){
+
+ module.BarcodeParser = instance.web.Class.extend({
+ init: function(attributes) {
+ var self = this;
+ this.nomenclature_id = attributes.nomenclature_id;
+ this.load_server_data();
+ },
+
+ models: [
+ {
+ model: 'barcode.nomenclature',
+ fields: ['name','rule_ids'],
+ domain: function(self){ return [] },
+ loaded: function(self,nomenclatures){
+ if (self.nomenclature_id) {
+ for (var i = 0; i < nomenclatures.length; i++) {
+ if (nomenclatures[i].id === self.nomenclature_id[0]) {
+ self.nomenclature = nomenclatures[i];
+ }
+ }
+ }
+ self.nomenclature = self.nomenclature || null;
+ },
+ }, {
+ model: 'barcode.rule',
+ fields: ['name','sequence','type','encoding','pattern','alias'],
+ domain: function(self){ return [['barcode_nomenclature_id','=',self.nomenclature ? self.nomenclature.id : 0]]; },
+ loaded: function(self,rules){
+ if (self.nomenclature) {
+ rules = rules.sort(function(a,b){ return a.sequence - b.sequence; });
+ self.nomenclature.rules = rules;
+ }
+ },
+ },
+ ],
+
+ // loads all the needed data on the sever. returns a deferred indicating when all the data has loaded.
+ load_server_data: function(){
+ var self = this;
+ var loaded = new $.Deferred();
+ var progress = 0;
+ var progress_step = 1.0 / self.models.length;
+ var tmp = {}; // this is used to share a temporary state between models loaders
+
+ function load_model(index){
+ if(index >= self.models.length){
+ loaded.resolve();
+ }else{
+ var model = self.models[index];
+ //self.pos_widget.loading_message(_t('Loading')+' '+(model.label || model.model || ''), progress);
+
+ var cond = typeof model.condition === 'function' ? model.condition(self,tmp) : true;
+ if (!cond) {
+ load_model(index+1);
+ return;
+ }
+
+ var fields = typeof model.fields === 'function' ? model.fields(self,tmp) : model.fields;
+ var domain = typeof model.domain === 'function' ? model.domain(self,tmp) : model.domain;
+ var context = typeof model.context === 'function' ? model.context(self,tmp) : model.context;
+ progress += progress_step;
+
+ if( model.model ){
+ new instance.web.Model(model.model).query(fields).filter(domain).context(context).all()
+ .then(function(result){
+ try{ // catching exceptions in model.loaded(...)
+ $.when(model.loaded(self,result,tmp))
+ .then(function(){ load_model(index + 1); },
+ function(err){ loaded.reject(err); });
+ }catch(err){
+ console.error(err.stack);
+ loaded.reject(err);
+ }
+ },function(err){
+ loaded.reject(err);
+ });
+ }else if( model.loaded ){
+ try{ // catching exceptions in model.loaded(...)
+ $.when(model.loaded(self,tmp))
+ .then( function(){ load_model(index +1); },
+ function(err){ loaded.reject(err); });
+ }catch(err){
+ loaded.reject(err);
+ }
+ }else{
+ load_model(index + 1);
+ }
+ }
+ }
+
+ try{
+ load_model(0);
+ }catch(err){
+ loaded.reject(err);
+ }
+ return loaded;
+ },
+
+ // returns the checksum of the ean13, or -1 if the ean has not the correct length, ean must be a string
+ ean_checksum: function(ean){
+ var code = ean.split('');
+ if(code.length !== 13){
+ return -1;
+ }
+ var oddsum = 0, evensum = 0, total = 0;
+ code = code.reverse().splice(1);
+ for(var i = 0; i < code.length; i++){
+ if(i % 2 == 0){
+ oddsum += Number(code[i]);
+ }else{
+ evensum += Number(code[i]);
+ }
+ }
+ total = oddsum * 3 + evensum;
+ return Number((10 - total % 10) % 10);
+ },
+
+ // returns a valid zero padded ean13 from an ean prefix. the ean prefix must be a string.
+ sanitize_ean: function(ean){
+ ean = ean.substr(0,13);
+
+ for(var n = 0, count = (13 - ean.length); n < count; n++){
+ ean = ean + '0';
+ }
+ return ean.substr(0,12) + this.ean_checksum(ean);
+ },
+
+ // attempts to interpret a barcode (string encoding a barcode Code-128)
+ // it will return an object containing various information about the barcode.
+ // most importantly :
+ // - code : the barcode
+ // - type : the type of the barcode (e.g. alias, unit product, weighted product...)
+ //
+ // - value : if the barcode encodes a numerical value, it will be put there
+ // - base_code : the barcode with all the encoding parts set to zero; the one put on
+ // the product in the backend
+ parse_barcode: function(barcode){
+ var self = this;
+ var parsed_result = {
+ encoding: '',
+ type:'error',
+ code:barcode,
+ base_code: barcode,
+ value: 0,
+ };
+ if (!self.nomenclature) {
+ return parsed_result;
+ }
+
+ function match_pattern(barcode,pattern){
+ if(barcode.length < pattern.replace(/[{}]/g, '').length){
+ return false; // Match of this pattern is impossible
+ }
+ var numerical_content = false; // Used to detect when we are between { }
+ for(var i = 0, j = 0; i < pattern.length; i++, j++){
+ var p = pattern[i];
+ if(p === "{" || p === "}"){
+ numerical_content = !numerical_content;
+ j--;
+ continue;
+ }
+
+ if(!numerical_content && p !== '*' && p !== barcode[j]){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function get_value(barcode,pattern){
+ var value = 0;
+ var decimals = 0;
+ var numerical_content = false;
+ for(var i = 0, j = 0; i < pattern.length; i++, j++){
+ var p = pattern[i];
+ if(!numerical_content && p !== "{"){
+ continue;
+ }
+ else if(p === "{"){
+ numerical_content = true;
+ j--;
+ continue;
+ }
+ else if(p === "}"){
+ break;
+ }
+
+ var v = parseInt(barcode[j]);
+ if(p === 'N'){
+ value *= 10;
+ value += v;
+ }else if(p === 'D'){ // FIXME precision ....
+ decimals += 1;
+ value += v * Math.pow(10,-decimals);
+ }
+ }
+ return value;
+ }
+
+ function get_basecode(barcode,pattern,encoding){
+ var base = '';
+ var numerical_content = false;
+ for(var i = 0, j = 0; i < pattern.length; i++, j++){
+ var p = pattern[i];
+ if(p === "{" || p === "}"){
+ numerical_content = !numerical_content;
+ j--;
+ continue;
+ }
+
+ if(numerical_content){
+ base += '0';
+ }
+ else{
+ base += barcode[j];
+ }
+ }
+ for(i=j; i<barcode.length; i++){ // Read the rest of the barcode
+ base += barcode[i];
+ }
+ if(encoding === "ean13"){
+ base = self.sanitize_ean(base);
+ }
+ return base;
+ }
+
+ var rules = self.nomenclature.rules;
+ for (var i = 0; i < rules.length; i++) {
+ if (match_pattern(barcode,rules[i].pattern)) {
+ if(rules[i].type === 'alias') {
+ barcode = rules[i].alias;
+ parsed_result.code = barcode;
+ parsed_result.type = 'alias';
+ }
+ else {
+ parsed_result.encoding = rules[i].encoding;
+ parsed_result.type = rules[i].type;
+ parsed_result.value = get_value(barcode,rules[i].pattern);
+ parsed_result.base_code = get_basecode(barcode,rules[i].pattern,parsed_result.encoding);
+ return parsed_result;
+ }
+ }
+ }
+ return parsed_result;
+ },
+ });
+} \ No newline at end of file