Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Is Angular JS Compatible with Odoo

    • 0
    • 1
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 2.55k
    Comment on it

    Odoo-7 and Odoo-8 support the angularjs using Odoo Web Services but Odoo-9 and Odoo-10 does not supports angular js, the reason is that Odoo-9 and Odoo-10 supports back-bone.js.

     

    Below are few steps how Odoo-7 and Odoo-8 works or support angular.js using Odoo Web Services:

    Step-1 How to Call Odoo-7 and Odoo-8 webservices from AngularJS.

    i) First of all you need to install OpenERP 7 or Odoo 8 for the complete installation process visit below link.

    http://findnerd.com/list/view/How-to-install-OpenERP-9-Odoo9-in-windows-7-8-and-10--/7755/

    (ii) Once you are done with ERP environment installation then you have to install Angular-1.4.

    Or 

    You have to Download dist/odoo.js or dist/odoo.min.js

    Step-2 Now add the below script to your page-

    <script src="path/to/angular-odoo-7/odoo-8/dist/odoo7/odoo8.js"></script>

     

    Step-3 Once the script is added after that add the module __odoo7/8__ to our applicaiton as shown below:

    Odoo_with_Angular('ourApplication name', ['odoo-7/8']);

    Step-4 After that use  Odoo services..

    Add __jsonRpc__ as a dependency with services.
    
    angular with odoo.module('logintest', ['$scope', 'jsonRpc', function($scope, jsonRpc) {
    	
    	jsonRpc.getDbList().then(function (result) {
    		//get databases list
    		$scope.dbs = result;
    	});
    
    	$scope.login = function(demp) {
    		jsonRpc.login(demo.db, demo.username, demo.password).then(function () {
    			//login successfull redirect here
    		}, function(reason) {
    			//display error
    		});
    	};
    }]);
    

     

    Step-5 I have posted following code to jsonrpc-services.js, you have to do same:

    'use strict';
    angular.module('odoo').provider('jsonRpc', function jsonRpcProvider() {
    
    	this.odooRpc = {
    		odoo_server: "",
    		uniq_id_counter: 0,
    		context: {'lang': 'fr_FR'},
    		shouldManageSessionId: false, //try without first
    		errorInterceptors: []
    	};
    
    	var preflightPromise = null;
    
    	this.$get = function($http, $q, $timeout) {
    
    		var odooRpc = this.odooRpc;
    
    		/**
    		* login
    		*		update cookie (session_id) in both cases
    		* @return promise
    		*		resolve promise if credentials ok
    		*		reject promise if credentials ko (with {title: wrong_login})
    		*		reject promise in other cases (http issues, server error)   
    		*/
    		odooRpc.login = function(db, login, password) {
    			var params = {
    				db : db,
    				login : login,
    				password : password
    			};
    
    			return odooRpc.sendRequest('/web/session/authenticate', params).then(function(result) {
    				if (!result.uid) {
    					cookies.delete_sessionId();
    					return $q.reject({ 
    						title: 'wrong_login',
    						message:"Username and password don't match",
    						fullTrace: result
    					});
    				}
    				odooRpc.context = result.user_context;
    				cookies.set_sessionId(result.session_id);
    				return result;
    			});
    		};
    
    		/**
    		* check if logged in or not
    		* @param force 
    		* 		if false -> check the cookies and return boolean
    		*		if true -> check with the server if still connected return promise
    		* @return boolean|| promise
    		*
    		*/
    		odooRpc.isLoggedIn = function (force) {
    			if (!force)
    				return cookies.get_sessionId().length > 0;
    
    			return odooRpc.getSessionInfo().then(function (result) {
    				cookies.set_sessionId(result.session_id);
    				return !!(result.uid); 
    			});
    		};
    
    		/**
    		* logout (delete cookie)
    		* @param force
    		*		if true try to connect with falsy ids
    		* @return null ||promise 
    		*/
    		odooRpc.logout = function (force) {
    			cookies.delete_sessionId();
    			if (force)
    				return odooRpc.getSessionInfo().then(function (r) { //get db from sessionInfo
    					if (r.db)
    						return odooRpc.login(r.db, '', '');
    				});
    			return $q.when();
    		};
    
    		odooRpc.searchRead = function(model, domain, fields) {
    			var params = {
    				model: model,
    				domain: domain,
    				fields: fields
    			}
    			return odooRpc.sendRequest('/web/dataset/search_read', params);
    		};
    
    		odooRpc.getSessionInfo = function(model, method, args, kwargs) {
    			return odooRpc.sendRequest('/web/session/get_session_info', {});
    		};
    
    		odooRpc.getServerInfo = function(model, method, args, kwargs) {
    			return odooRpc.sendRequest('/web/webclient/version_info', {});
    		};
    
    		odooRpc.getDbList = function() {
    			return odooRpc.sendRequest('/web/database/get_list', {});
    		};
    		odooRpc.syncDataImport = function(model, func_key, base_domain, filter_domain, limit, object) {
    			return odooRpc.call(model, 'get_sync_data', [
    				func_key, object.timekey, base_domain, filter_domain, limit
    			], {}).then(function(result) {
    					//if (object.timekey === result.timekey) TODO: add mutlidomain before uncomment
    					// return; //no change since last run
    					object.timekey = result.timekey; 
    					
    					angular.forEach(result.remove_ids, function(id) {
    						delete object.data[id];
    					});
    
    					if (Object.keys(result.data).length) {
    						angular.merge(object.data, result.data); ///merge deeply old with new
    						return odooRpc.syncDataImport(model, func_key, base_domain, filter_domain, limit, object);
    					}
    			});
    		};
    
    		odooRpc.syncImportObject = function(params) {
    			/* params = {
    					model: 'odoo.model',
    					func_key: 'my_function_key',
    					domain: [],
    					limit: 50,
    					interval: 5000,
    					}
    
    			 When an error happens, the sync cycle is interrupted.
    
    			 An optional parameter 'onErrorRetry' can be specified. If its value is
    			 true, then the sync cycle will continue on the next interval even when
    			 errors occur. For a more fine-grained control over the retries,
    			 'onErrorRetry' could also be a function, taking the error as argument.
    			 It should call 'nextSync()' on the synchronized object's API to delay
    			 the next sync iteration.
    
    			 Example:
    
    				params = {
    					...
    					onErrorRetry: function(sync, err) {
    						if(shouldRetry(err)) {
    							sync.nextSync();
    						}
    					}
    					}
    
    			 return a synchronized object where you can access
    			 to the data using object.data
    			*/
    			var stop = false;
    			var watchers = [];
    			var object = { 
    				data: {}, 
    				timekey: null, 
    				stopCallback: function () {
    					stop = true;
    				},
    				watch: function(fun) {
    					watchers.push(fun);
    				},
    				nextSync: nextSync
    			};
    
    			function nextSync(interval) {
    				if(!stop) {
    					$timeout(sync, interval || params.interval);
    				}
    			}
    
    			function runWatchers(data) {
    				watchers.forEach(function (fun) {
    					fun(object);
    				});
    			}
    
    			var errorCallback = null;
    			if(angular.isFunction(params.onErrorRetry)) {
    				errorCallback = function(err) { params.onErrorRetry(object, err); };
    			} else if(params.onErrorRetry) {
    				errorCallback = function(err) { nextSync(); };
    			}
    
    			function sync() {
    
    				odooRpc.syncDataImport(
    					params.model,
    					params.func_key,
    					params.base_domain,
    					params.filter_domain,
    					params.limit,
    					object)
    				.then(nextSync)
    				.then(runWatchers)
    				.catch(errorCallback);
    			}
    			sync();
    
    			return object;
    		};
    
    		odooRpc.call = function(model, method, args, kwargs) {
    
    			kwargs = kwargs || {};
    			kwargs.context = kwargs.context || {};
    			angular.extend(kwargs.context, odooRpc.context);
    
    			var params = {
    				model: model,
    				method: method,
    				args: args,
    				kwargs: kwargs,
    			};
    			return odooRpc.sendRequest('/web/dataset/call_kw', params);
    		};
    
    
    		/**
    		* base function
    		*/
    		odooRpc.sendRequest = function(url, params) {
    
    			/** (internal) build request for $http
    			* keep track of uniq_id_counter
    			* add session_id in the request (for Odoo v7 only) 
    			*/
    			function buildRequest(url, params) {
    				odooRpc.uniq_id_counter += 1;
    				if (odooRpc.shouldManageSessionId)
    					params.session_id = cookies.get_sessionId();
    
    				var json_data = {
    					jsonrpc: '2.0',
    					method: 'call',
    					params: params, //payload
    				};
    				var headers = {
    					'Content-Type': 'application/json',
    					'X-Openerp-Session-Id': cookies.get_sessionId()
    				}
    				return {
    					'method' : 'POST',
    					'url' : odooRpc.odoo_server + url,
    					'data' : JSON.stringify(json_data),
    					'headers': headers,
    					'id': ("r" + odooRpc.uniq_id_counter),
    				};
    			}
    
    			/** (internal) Odoo do some error handling and doesn't care
    			* about HTTP response code
    			* catch errors codes here and reject
    			*	@param response $http promise
    			*	@return promise 
    			*		if no error : response.data ($http.config & header stripped)
    			*		if error : reject with a custom errorObj
    			*/
    			function handleOdooErrors(response) {
    				if (!response.data.error)
    					return response.data;
    
    				var error = response.data.error;
    				var errorObj = {
    					title: '',
    					message:'',
    					fullTrace: error
    				};
    
    				if (error.code === 200 && error.message === "Odoo Server Error" && error.data.name === "werkzeug.exceptions.NotFound") {
    					errorObj.title = 'page_not_found';
    					errorObj.message = 'HTTP Error';
    				} else if ( (error.code === 100 && error.message === "Odoo Session Expired") || //v8
    							(error.code === 300 && error.message === "OpenERP WebClient Error" && error.data.debug.match("SessionExpiredException")) //v7
    						) {
    							errorObj.title ='session_expired';
    							cookies.delete_sessionId();
    				} else if ( (error.message === "Odoo Server Error" && /FATAL:  database "(.+)" does not exist/.test(error.data.message))) {
    					errorObj.title = "database_not_found";
    					errorObj.message = error.data.message;
    				} else if ( (error.data.name === "openerp.exceptions.AccessError")) {
    					errorObj.title = 'AccessError';
    					errorObj.message = error.data.message;
    				} else {
    					var split = ("" + error.data.fault_code).split('\n')[0].split(' -- ');
    					if (split.length > 1) {
    						error.type = split.shift();
    						error.data.fault_code = error.data.fault_code.substr(error.type.length + 4);
    					}
    
    					if (error.code === 200 && error.type) {
    						errorObj.title = error.type;
    						errorObj.message = error.data.fault_code.replace(/\n/g, "<br />");
    					} else {
    						errorObj.title = error.message;
    						errorObj.message = error.data.debug.replace(/\n/g, "<br />");
    					}
    				}
    				odooRpc.errorInterceptors.forEach(function (i) {
    					i(errorObj);
    				});
    				return $q.reject(errorObj)
    			}
    
    			/**
    			*	(internal)
    			*	catch HTTP response code (not handled by Odoo ie Error 500, 404)
    			*	@params $http rejected promise
     			*	@return promise
    			*/
    			function handleHttpErrors(reason) {
    				var errorObj = {title:'http', fullTrace: reason, message:'HTTP Error'};
    				odooRpc.errorInterceptors.forEach(function (i) {
    					i(errorObj);
    				});
    				return $q.reject(errorObj);
    			}
    
    			/**
    			*	(internal) wrapper around $http for handling errors and build request
    			*/
    			function http(url, params) {
    				var req = buildRequest(url, params);
    				return $http(req).then(handleOdooErrors, handleHttpErrors);
    			}
    
    			/** (internal) determine if session_id shoud be managed by this lib
    			* more info: 
    			*	in v7 session_id is returned by the server in the payload 
    			*		and it should be added in each request's paylaod.
    			*		it's 
    			*
    			*	in v8 session_id is set as a cookie by the server
    			*		therefor the browser send it on each request automatically
    			*
    			*	in both case, we keep session_id as a cookie to be compliant with other odoo web clients 
    			*
    			*/
    			function preflight() {
    				//preflightPromise is a kind of cache and is set only if the request succeed
    				return preflightPromise || http('/web/webclient/version_info', {}).then(function (reason) {
    					odooRpc.shouldManageSessionId = (reason.result.server_serie < "8"); //server_serie is string like "7.01"
    					preflightPromise = $q.when(); //runonce
    				});
    			}
    
    			return preflight().then(function () {
    				return http(url, params).then(function(response) {
    					var subRequests = [];
    					if (response.result.type === "ir.actions.act_proxy") {
    						angular.forEach(response.result.action_list, function(action) {
    							subRequests.push($http.post(action['url'], action['params']));
    						});
    						return $q.all(subRequests);
    					} else
    						return response.result;
    				});
    			});
    		};
    
    		return odooRpc;
    	};
    
    	var cookies = (function() {
    		var session_id; //cookies doesn't work with Android Default Browser / Ionic
    		return {
    			delete_sessionId: function() {
    				session_id = null;
    				document.cookie  = 'session_id=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
    			},
    			get_sessionId: function () {
    				return document.cookie.split('; ')
    				.filter(function (x) { return x.indexOf('session_id') === 0; })
    				.map(function (x) { return x.split('=')[1]; })
    				.pop() || session_id || "";
    			},
    			set_sessionId: function (val) {
    				document.cookie = 'session_id=' + val;
    				session_id = val;
    			}
    		};
    	}());
    })
    
    .controller('', () => {})
    
    .service ('', () => {})
    ;

     

    Note: You can download the attached module for further use.

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: