exportoo/odoo-rpc.py

488 lines
12 KiB
Python
Executable File

#!/usr/bin/env python
# Usage:
# ./odoo-export.py <MODEL> <METHOD> [<param> [<param> [<param>]]]
from __future__ import print_function
import os
import sys
import json
import odoorpc # pip install odoorpc
from renderers import render, tsv
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
# CONFIG
FOLDER = '/home/dig/odoo-export/datas'
# PARAMS = sys.argv[1:]
PARAMS = []
OPTS = {}
for param in sys.argv[1:]:
if param[0] == '-':
kv = param[1:].split( '=' )
if len(kv) == 1:
OPTS[kv[0]] = False
else:
OPTS[kv[0]] = kv[1]
elif param[0] == '+':
kv = param[1:].split( '=' )
if len(kv) == 1:
OPTS[kv[0]] = True
else:
OPTS[kv[0]] = kv[1]
else:
PARAMS.append( param )
MODEL_IGNORE = []
with open(".modelignore", "r") as file:
for line in file:
MODEL_IGNORE.append(line.strip())
eprint( len(sys.argv), 'argument(s):', PARAMS, OPTS )
eprint( MODEL_IGNORE )
def jlog( obj ):
print( json.dumps(obj, indent=4) ) #"\t") )
def ensure_dir(d):
if not os.path.exists(d):
os.makedirs(d)
def args2domains( list ):
domains = []
while len(list) > 0:
str = list[0]
if str == '&' or str == '|' or str == '!':
domains.append( str )
list = list[1:]
else:
domains.append( (list[0], list[1], list[2]) )
list = list[3:]
return domains
# eprint( args2domains(sys.argv[3:]) )
#quit()
odoo = None
def autolog():
# Then, use the odoorpc.ODOO.load() class method:
odoo = odoorpc.ODOO.load('session')
# Or, if you have saved your configuration in another file:
# odoo = odoorpc.ODOO.load('tutorial', '~/my_own_odoorpcrc')
# You can check available sessions with odoorpc.ODOO.list(), and remove them with odoorpc.ODOO.remove():
# odoorpc.ODOO.list()
# ['session']
# odoorpc.ODOO.remove('tutorial')
# 'tutorial' not in odoorpc.ODOO.list()
# True
# Current user
user = odoo.env.user
eprint( 'User: ', user.name ) # name of the user connected
eprint( 'Company: ', user.company_id.name ) # the name of its company
eprint( '_________________________' )
return odoo
# Prepare the connection to the server
# odoo = odoorpc.ODOO('localhost', port=8069)
# Check available databases
# eprint( 'Databases: ', odoo.db.list() )
#jlog( odoo.db.list() )
# Simple 'raw' query
#user_data = odoo.execute('res.users', 'read', [user.id])
#print(user_data)
# Use all methods of a model
#if 'sale.order' in odoo.env:
# Order = odoo.env['sale.order']
# order_ids = Order.search([])
# for order in Order.browse(order_ids):
# print(order.name)
# products = [line.product_id.name for line in order.order_line]
# print(products)
# Update data through a record
#user.name = "Brian Jones"
def json_path( model, id ):
return "%s/%s.json" % ( FOLDER, Muid(model, id) )
def Muid( model, id ):
return "%s/%s" % ( model, id )
def get_schema( name ):
eprint( 'get_schema' )
Model = odoo.env['ir.model']
ids = Model.search([( 'model', '=', name )])
#print( ids )
for model in Model.browse( ids ):
obj = model.read()[0]
fields = [ field.read()[0] for field in model.field_id ]
#jlog( fields )
obj['field_id'] = fields
jlog( transform_model(obj) )
eprint( "%s/schemas/%s.json" % ( FOLDER, model.model ) )
def transform_model( obj ):
return { "name": obj['model'], "modules": obj['modules'], 'fields': [ {} for field in obj['field_id'] ] }
def rel_fields( model ):
Model = odoo.env['ir.model.fields']
ids = Model.search([( 'model_id.model', '=', model ), ('relation','!=','false')])
return Model.browse( ids )
# def tsv( *fields ):
# print( *fields, sep='\t' )
# def render_tsv( model, list ):
# if model in cols:
# _cols = cols[model]
# else:
# _cols = cols['']
# tsv( *_cols )
# for obj in list:
# tsv( *[ obj[col] for col in _cols] )
# #def render_json( model, obj ):
# def render( opts ): # +format=json,xml,csv +json +tsv
# if opts.json or ( opts.format and 'json' in opts.format ):
# render_json( list )
# if opts.tsv or ( opts.format and 'tsv' in opts.format ):
# render_tsv( model, list )
# # if opts.csv or ( opts.format and 'csv' in opts.format ):
# # if opts.xml or ( opts.format and 'xml' in opts.format ):
# COMMANDS
def login( server = None, port = None, db = None, user = None, passwd = None ):
if server:
tsv( 'Server:', server )
else:
server = raw_input('Server address: ')
if port:
tsv( 'Port:', port )
else:
port = raw_input('Port: ')
odoo = odoorpc.ODOO( server, port=port )
print( 'Connected to ' + server + ':' + port )
print( 'Available databases:' )
for _db in odoo.db.list():
print( _db )
if db:
tsv( 'Database:', db )
else:
db = raw_input('Choose database: ')
if user:
tsv( 'User:', user )
else:
user = raw_input('User: ')
if passwd:
tsv( 'Password:', '****************' )
else:
passwd = raw_input('Password: ')
eprint( server, port, user, passwd )
user = odoo.login( db, user, passwd )
odoo.save('session')
# # By default, these informations are stored in the ~/.odoorpcrc file. You can however use another file:
# # odoo.save('tutorial', '~/my_own_odoorpcrc')
def search( model, domains ):
Model = odoo.env[model]
ids = Model.search( domains )
return ids
# render_tsv( model, Model.browse(ids) )
# print( 'id', 'name', sep='\t' )
# for inst in Model.browse( ids ):
# render_tsv( model, inst )
def fields( model, domains ):
Model = odoo.env['ir.model.fields']
domains = [( 'model_id.model', '=', model )].append( domains )
ids = Model.search( domains )
render( OPTS, 'ir.model.fields', Model.browse(ids) )
stack = []
current_exports = []
def lookup_model( muid ):
eprint( "> Lookup model: %s" % (muid) )
# _stack = []
_tree = {}
# _ctree = _tree
model, id = muid.split( '/' )
id = int(id)
eprint( model, id )
_tree[muid] = {}
# _ctree = _tree[muid]
if model in odoo.env:
rfields = rel_fields( model )
eprint( rfields )
try:
inst = odoo.env[model].browse( id )
except:
_tree[muid]['error'] = 'Instance %s not found' % (muid)
return _tree
# data = inst.read()[0]
# size = len( json.dumps(data, indent=4) )
# filename = json_path( model, inst.id )
# _tree[muid]['size'] = size
for field in rfields:
# if data[field.name]:
# _tree[muid][field.name] = {}
_value = getattr( inst, field.name )
print( field.name )
print( _value )
if _value:
print( field.name, field.ttype )
if field.ttype == 'many2one':
id = _value.id
# _stack.append( Muid(field.relation, id) )
_tree[muid][field.name] = [ Muid(field.relation, id) ]
if field.ttype == 'one2many':
_tree[muid][field.name] = [ Muid(field.relation, id) for id in _value.ids ]
# for id in _value.ids:
# _stack.append( Muid(field.relation, id) )
# if field.ttype == 'many2many':
# if field.ttype == 'reference':
else:
_tree[muid]['error'] = 'Model do not exists'
return _tree
def lookup_recs( model, domains ):
eprint( "> Lookup recursif: %s %s" % (model,domains) )
if model in MODEL_IGNORE:
eprint( 'IGNORED' )
return
Model = odoo.env[model]
ids = Model.search( domains )
# rfields = rel_fields( model )
# eprint( rfields )
for inst in Model.browse( ids ):
tree = lookup_model( Muid(model, inst.id) )
filename = json_path( model, inst.id )
if filename in [item['file'] for item in stack]:
continue
tree['file'] = filename
# stack.append({ 'model': model, 'id': inst.id, 'file': filename, 'data': size })
stack.append( tree )
return stack
def lookup( model, domains ):
eprint( "> Lookup: %s %s" % (model,domains) )
if model in MODEL_IGNORE:
print( 'IGNORED' )
return
Model = odoo.env[model]
ids = Model.search( domains )
rfields = rel_fields( model )
eprint( rfields )
for inst in Model.browse( ids ):
data = inst.read()[0]
size = len( json.dumps(data, indent=4) )
filename = json_path( model, inst.id )
if filename in [item['file'] for item in stack]:
continue
# print( 'Preparing data for %s' % (filename) )
stack.append({ 'model': model, 'id': inst.id, 'file': filename, 'data': size })
for field in rfields:
#data[field.name] = inst[field.name].read()[0]
#eprint( data[field.name] )
if field.relation in MODEL_IGNORE:
continue
if data[field.name]:
tsv( 'Field: ', field.ttype, field.name, field.relation, data[field.name] )
if field.ttype == 'many2one':
id = data[field.name][0]
_filename = json_path( field.relation, id )
print( field.ttype, field.relation, id, _filename )
if not os.path.exists( _filename ):
lookup( field.relation, [('id','=',id)] )
else:
print('Already exists %s' % (_filename) )
if field.ttype == 'one2many':
for id in data[field.name]:
_filename = json_path( field.relation, id )
print( field.ttype, field.relation, id, _filename )
if not os.path.exists( _filename ):
lookup( field.relation, [('id','=',id)] )
else:
print('Already exists %s' % (_filename) )
print( stack )
def export_json( model, domains ):
print( "> Export to json: %s %s" % (model,domains) )
if model in MODEL_IGNORE:
print( 'IGNORED' )
return
Model = odoo.env[model]
ids = Model.search( domains )
ensure_dir( "%s/%s" % (FOLDER, model) )
rfields = rel_fields( model )
eprint( rfields )
for inst in Model.browse( ids ):
data = inst.read()[0]
filename = "%s/%s/%s.json" % ( FOLDER, model, inst.id )
if filename in current_exports:
continue
print( 'Preparing data for %s' % (filename) )
current_exports.append( filename )
# Write pretty print JSON data to file
with open( filename, "w") as write_file:
json.dump(data, write_file, indent=4)
print( "%s written" % (filename) )
for field in rfields:
#data[field.name] = inst[field.name].read()[0]
#eprint( data[field.name] )
if field.relation in MODEL_IGNORE:
continue
if data[field.name]:
tsv( 'Field: ', field.ttype, field.name, field.relation, data[field.name] )
if field.ttype == 'many2one':
id = data[field.name][0]
_filename = "%s/%s/%s.json" % ( FOLDER, field.relation, id )
print( field.ttype, field.relation, id, _filename )
if not os.path.exists( _filename ):
export_json( field.relation, [('id','=',id)] )
else:
print('Already exists %s' % (_filename) )
if field.ttype == 'one2many':
for id in data[field.name]:
_filename = "%s/%s/%s.json" % ( FOLDER, field.relation, id )
print( field.ttype, field.relation, id, _filename )
if not os.path.exists( _filename ):
export_json( field.relation, [('id','=',id)] )
else:
print('Already exists %s' % (_filename) )
# AUTO EXEC
MODEL = PARAMS[0]
if len(PARAMS) > 1:
METHOD = PARAMS[1]
if PARAMS[0] == 'login':
login( *PARAMS[1:] )
quit()
else:
odoo = autolog()
if MODEL in odoo.env:
Model = odoo.env[MODEL]
if METHOD == 'search':
# render_tsv( odoo.env[MODEL].browse( odoo.env[MODEL].search( args2domains(PARAMS[2:]) ) ) )
ids = search( MODEL, args2domains(PARAMS[2:]) )
render( OPTS, MODEL, Model.browse(ids) )
#ids = Model.search( args2domains(PARAMS[2:]) )
#print( 'id', 'name', sep='\t' )
#for inst in Model.browse( ids ):
# render_tsv( MODEL, inst )
if METHOD == 'browse':
ids = PARAMS[2:]
ids = [ int(s) for s in ids ]
#print( ids )
for inst in Model.browse( ids ):
jlog( inst.read()[0] )
if METHOD == 'lookup':
print( lookup( MODEL, args2domains(PARAMS[2:]) ) )
if METHOD == 'lookup-model':
jlog( lookup_model( Muid(MODEL,PARAMS[2]) ) )
if METHOD == 'lookup-recs':
jlog( lookup_recs( MODEL, args2domains(PARAMS[2:]) ) )
if METHOD == 'export-json':
export_json( MODEL, args2domains(PARAMS[2:]) )
if METHOD == 'fields_get':
jlog( Model.fields_get() )
if METHOD == 'fields':
Model = odoo.env['ir.model.fields']
ids = Model.search([( 'model_id.model', '=', MODEL )])
render( OPTS, MODEL, Model.browse(ids) )
#for inst in Field.browse( ids ):
# render_tsv( 'ir.model.fields', inst )
elif MODEL == 'db':
if METHOD == 'list':
jlog( odoo.db.list() )
elif MODEL == 'schema':
get_schema( METHOD )
# if __name__ == "__main__":
# import sys
# fib(int(sys.argv[1]))