README.md

Why use Ooor?

Ooor is an administration Swiss Army knife in interactive IRB sessions. It lets you connect remotely to any running OpenERP instance without stopping it, without compromising its security. It has tab auto-completion and object introspection features.

Ooor is the basis for unleashed web development, using any Rack framework such as Sinatra or Rails.

OpenERP is all the rage for ERP back-offices, but sometimes you want freedom and scalablity for your web front ends and this is exactly what Ooor offers you. It enables you to just reuse OpenERP Model layer (yay! no data duplication!) and let you build the other layers much the way you want, possibly standing on the shoulders of giants like Rails. Ooor even has an optionnal Rack filter that enables you to proxy some OpenERP applications of your choice (say the shopping cart for instance) and share the HTTP session with it. Ooor is also published under the MIT licence so it frees you from the OpenERP AGPL license contamination for your web developements.

Related projects - a full web stack!

Ooorest, Ooor is the Model layer of MVC. Ooorest is the Controller layer, enforcing a clean Railish REST API and offering handy helper to use OpenERP in your Rails application.

Erpify, Erpify is OpenERP inside the Liquid non evaling language, that is the templating language of Shopify or LocomotiveCMS for instance.

Locomotive-erpify, Erpify for LocomotiveCMS, both the engine and the Wagon local editor

Solarize, pulling data from OpenERP relational database may not scale to your need. No problem with Solarize: you can index your OpenERP data with the Solerp OpenERP module, then search it using SolR API and even load it from SolR without even hitting OpenERP!

TerminatOOOR, a Pentaho ETL Kettle plugin allowing to push/pull data into/from OpenERP with an incomparable flexibility and yet benefit all standard ETL features, including the AgileBI OLAP business intelligence plugin.

How?

OpenERP is a Python based open source ERP. But every action in OpenERP is actually exposed as a webservice (SOA orientation, close to being RESTful).
Ooor doesn't connect to the OpenERP database, instead it uses the OpenERP data access JSON API so it fully enforces OpenERP security model and business logic.

Ooor is less than 2000 lines of code. It has a test coverage of around 80%. It doesn't embed any business rule, it's just a client to OpenERP. The code of Ooor is modeled after Rails ActiveModel, ActiveResource and ActiveRecord layers.

More specifically, an OpenERP Ooor proxy implements the ActiveModel API. Instead of depending on ActiveResource which is actually a bit different (not multi-tenant, little access right management), we copied a tiny subset of it in the mini_active_resource.rb file and OpenERP proxies include this module. Finally Ooor emulates the ActiveRecord API wherever possible delegating its requests to OpenERP using OpenERP domain S expressions instead of SQL. The ActiveRecord API emulation is actually pretty good: think Ooor looks more like ActiveRecord than Mongoid; it has associations, surface ARel API, Reflection API, can be paginated via Kaminary, can be integrated with SimpleForm or Cocoon seamlessly...

Ooor features several session modes: in the default IRB console usage it uses a global login scheme and generate constants for your OpenERP proxies, such as ProductProduct for the product.product OpenERP object much like Rails ActiveRecord. In web mode instead, you can have several sessions and do session['product.product'] to get a proxy to the Product object matching your current session credentials, chosen database and OpenERP url (yes Ooor is not only multi-database like OpenEP, it's in fact multi-OpenERP!)

Installation

$ gem install ooor

(Warning Ooor has been ureleased for several months, don't hesitate to run the git version instead)

Trying it simply

Once you installed the OOOR gem, you get a new OOOR command line. Basic usage is:

$ ooor username.database@host:xmlrpc_port

This will bring you in a standard IRB interpreter with an OOOR client already connected to your OpenERP server so you can start playing with it.

(J)Ruby on Rails application:

API usage

Note: Ruby proxy objects are named after OpenERP models in but removing the '.' and using CamelCase.
(we remind you that OpenERP tables are also named after OpenERP models but replacing the '.' by '_'.)

ResPartner.find(:all, :domain=>[['supplier', '=', 1],['active','=',1]])
#More subtle now, remember OpenERP use a kind of inverse polish notation for complex domains,#here we look for a product in category 1 AND which name is either 'PC1' OR 'PC2':ProductProduct.find(:all, :domain=>[['categ_id','=',1],'|',['name', '=', 'PC1'],['name','=','PC2']])

OpenERP context support (same as OpenERP):

ProductProduct.find(1, :context => {:my_key => 'value'})

Request params or ActiveResource equivalence of OpenERP domain (but degraded as only the = operator is supported, else use domain):

Note: currently OOOR doesn't deal with the View layer, or has a very limited support for forms for the wizards.
So, it's not possible so far for OOOR to know an on_change signature. Because of this, the on_change syntax is bit awkward
as you will see (fortunately OpenERP SA announced they will fix that on_change API in subsequent v6 OpenERP releases):
you need to explicitely tell the on_change name, the parameter name that changed, the new value and finally
enfore the on_change syntax (looking at the OpenERP model code or view or XML/RPC logs will help you to find out). But
ultimately it works:

inv =AccountInvoice.find(4)
#in case the inv.state is 'draft', do inv.wkf_action('invoice_open')
wizard = inv.old_wizard_step('account.invoice.pay') #tip: you can inspect the wizard fields, arch and datas
wizard.reconcile({:journal_id => 6, :name =>"from_rails"}) #if you want to pay all; will give you a reloaded invoice
inv.state
#=> "paid"#or if you want a payment with a write off:
wizard.writeoff_check({"amount" => 12, "journal_id" => 6, "name" =>'from_rails'}) #use the button name as the wizard method
wizard.reconcile({required missing write off fields...}) #will give you a reloaded invoice because state is 'end'#TODO test and document new osv_memory wizards API

Absolute OpenERP ids aka ir_model_data:

just like Rails fixtures, OpenERP supports absolute ids for its records, especially those imported from XML or CSV.
We are here speaking about the string id of the XML or CSV records, eventually prefixed by the module name.
Using those ids rather than the SQL ids is a good idea to avoid relying on a particular installation.
In OOOR, you can both retrieve one or several records using those ids, like for instance:

ProductCategory.find('product.product_category_3')

Notice that the 'product.' module prefix is optional here but important if you have similar ids in different module scopes.
You can also create a resource and it's ir_model_data record alltogether using the ir_mode_data_id param:

To obtain the binary data of an object report simply use the function get_report_data(report_name). This function returns a list that contains the binary data encoded in base64 and a string with the file format.
Example:

inv =AccountInvoice.find(3)
report = inv.get_report_data('account.invoice') #account.invoice is the service name defined in Invoices report#Save the report to a file#report[1] contains the file extension and report[0] contains the binary data of the report encoded in base64File.open("invoice_report.#{report[1]}", "w") {|f| f.write(Base64.decode64(report[0]))}

Instead, every Ooor business objects can also belong to some specific user. To achieve that, generate your object passing
proper :user_id and :password parameters inside the context of the method creating the object (typically a find).
Notice that methods invoked on an objet use the same credentials as the business objects.
Objects generated by this object (by a call to an association for instance) will also have the same credentials.