ooor 1.6.5 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +131 -88
- data/bin/ooor +4 -2
- data/lib/app/helpers/core_helpers.rb +137 -0
- data/lib/app/models/base64.rb +14 -25
- data/lib/app/models/common_service.rb +3 -15
- data/lib/app/models/db_service.rb +6 -17
- data/lib/app/models/ooor_client.rb +3 -15
- data/lib/app/models/open_object_resource.rb +40 -41
- data/lib/app/models/relation.rb +4 -16
- data/lib/app/models/serialization.rb +5 -0
- data/lib/app/models/type_casting.rb +8 -3
- data/lib/app/models/uml.rb +26 -35
- data/lib/app/ui/action_window.rb +13 -19
- data/lib/app/ui/client_base.rb +4 -21
- data/lib/app/ui/form_model.rb +4 -15
- data/lib/ooor.rb +50 -46
- data/spec/ooor_spec.rb +49 -29
- metadata +38 -37
- data/agpl-3.0-licence.txt +0 -661
- data/lib/app/ui/menu.rb +0 -34
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009-2012 Raphaël Valyi - Akretion LTDA
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
OOOR - OpenObject On
|
1
|
+
OOOR - OpenObject On Ruby:
|
2
2
|
====
|
3
3
|
|
4
4
|
<table>
|
@@ -106,14 +106,18 @@ This will bring you in a standard IRB interpreter with an OOOR client already co
|
|
106
106
|
|
107
107
|
Let's test OOOR in an irb console (irb command):
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
```ruby
|
110
|
+
require 'rubygems'
|
111
|
+
require 'ooor'
|
112
|
+
Ooor.new(:url => 'http://localhost:8069/xmlrpc', :database => 'mybase', :username => 'admin', :password => 'admin')
|
113
|
+
```
|
112
114
|
|
113
115
|
This should load all your OpenERP models into Ruby proxy Activeresource objects. Of course there are option to load only some models.
|
114
116
|
Let's try to retrieve the user with id 1:
|
115
117
|
|
116
|
-
|
118
|
+
```ruby
|
119
|
+
ResUsers.find(1)
|
120
|
+
```
|
117
121
|
|
118
122
|
(in case you have an error like "no such file to load -- net/https", then on Debian/Ubuntu, you might need to do before: apt-get install libopenssl-ruby)
|
119
123
|
|
@@ -131,52 +135,62 @@ Note: Ruby proxies objects are named after OpenERP models in but removing the '.
|
|
131
135
|
|
132
136
|
Basic finders:
|
133
137
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
138
|
+
```ruby
|
139
|
+
ProductProduct.find(1)
|
140
|
+
ProductProduct.find([1,2])
|
141
|
+
ProductProduct.find([1])
|
142
|
+
ProductProduct.find(:all)
|
143
|
+
ProductProduct.find(:last)
|
144
|
+
```
|
140
145
|
|
141
146
|
OpenERP domain support (same as OpenERP):
|
142
147
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
148
|
+
```ruby
|
149
|
+
ResPartner.find(:all, :domain=>[['supplier', '=', 1],['active','=',1]])
|
150
|
+
#More subtle now, remember OpenERP use a kind of inverse polish notation for complex domains,
|
151
|
+
#here we look for a product in category 1 AND which name is either 'PC1' OR 'PC2':
|
152
|
+
ProductProduct.find(:all, :domain=>[['categ_id','=',1],'|',['name', '=', 'PC1'],['name','=','PC2']])
|
153
|
+
```
|
147
154
|
|
148
155
|
|
149
156
|
OpenERP context support (same as OpenERP):
|
150
157
|
|
151
|
-
|
152
|
-
|
158
|
+
```ruby
|
159
|
+
ProductProduct.find(1, :context => {:my_key => 'value'})
|
160
|
+
```
|
153
161
|
|
154
162
|
Request params or ActiveResource equivalence of OpenERP domain (but degraded as only the = operator is supported, else use domain):
|
155
163
|
|
156
|
-
|
157
|
-
|
164
|
+
```ruby
|
165
|
+
ResPartner.find(:all, :params => {:supplier => true})
|
166
|
+
```
|
158
167
|
|
159
168
|
OpenERP search method:
|
160
169
|
|
161
|
-
|
170
|
+
```ruby
|
171
|
+
ResPartner.search([['name', 'ilike', 'a']], 0, 2)
|
172
|
+
```
|
162
173
|
|
163
174
|
Arguments are: domain, offset=0, limit=false, order=false, context={}, count=false
|
164
175
|
|
165
176
|
|
166
177
|
Relations (many2one, one2many, many2many) support:
|
167
178
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
179
|
+
```ruby
|
180
|
+
SaleOrder.find(1).order_line #one2many relation
|
181
|
+
p = ProductProduct.find(1)
|
182
|
+
p.product_tmpl_id #many2one relation
|
183
|
+
p.taxes_id #automagically reads man2many relation inherited via the product_tmpl_id inheritance relation
|
184
|
+
p.taxes_id = [1,2] #save a many2many relation, notice how we bypass the awkward OpenERP syntax for many2many (would require [6,0, [1,2]]) ,
|
185
|
+
p.save #assigns taxes with id 1 and 2 as sale taxes,
|
186
|
+
see [the official OpenERP documentation](http://doc.openerp.com/developer/5_18_upgrading_server/19_1_upgrading_server.html?highlight=many2many)```
|
175
187
|
|
176
188
|
|
177
189
|
Inherited relations support:
|
178
190
|
|
179
|
-
|
191
|
+
```ruby
|
192
|
+
ProductProduct.find(1).categ_id #where categ_id is inherited from the ProductTemplate
|
193
|
+
```
|
180
194
|
|
181
195
|
Please notice that loaded relations are cached (to avoid hitting OpenERP over and over)
|
182
196
|
until the root object is reloaded (after save/update for instance).
|
@@ -184,48 +198,57 @@ until the root object is reloaded (after save/update for instance).
|
|
184
198
|
|
185
199
|
Load only specific fields support (faster than loading all fields):
|
186
200
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
201
|
+
```ruby
|
202
|
+
ProductProduct.find(1, :fields=>["state", "id"])
|
203
|
+
ProductProduct.find(:all, :fields=>["state", "id"])
|
204
|
+
ProductProduct.find([1,2], :fields=>["state", "id"])
|
205
|
+
ProductProduct.find(:all, :fields=>["state", "id"])
|
206
|
+
```
|
191
207
|
|
192
208
|
even in relations:
|
193
209
|
|
194
|
-
|
195
|
-
|
210
|
+
```ruby
|
211
|
+
SaleOrder.find(1).order_line(:fields => ["state"])
|
212
|
+
```
|
196
213
|
|
197
214
|
Create:
|
198
215
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
216
|
+
```ruby
|
217
|
+
pc = ProductCategory.new(:name => 'Categ From Rails!')
|
218
|
+
#<ProductCategory:0xb702c42c @prefix_options={}, @attributes={"name"=>"Categ From Rails!"}>
|
219
|
+
pc.create
|
220
|
+
pc.id
|
221
|
+
#$ => 14
|
222
|
+
```
|
204
223
|
|
205
224
|
|
206
225
|
Update:
|
207
226
|
|
208
|
-
|
209
|
-
|
210
|
-
|
227
|
+
```ruby
|
228
|
+
pc.name = "A new name"
|
229
|
+
pc.save
|
230
|
+
```
|
211
231
|
|
212
232
|
Copy:
|
213
233
|
|
214
|
-
|
215
|
-
|
234
|
+
```ruby
|
235
|
+
copied_object = pc.copy({:categ_id => 2}) #first optionnal arg is new default values, second is context
|
236
|
+
```
|
216
237
|
|
217
238
|
Delete:
|
218
239
|
|
219
|
-
|
220
|
-
|
240
|
+
```ruby
|
241
|
+
pc.destroy
|
242
|
+
```
|
221
243
|
|
222
244
|
Call workflow:
|
223
245
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
246
|
+
```ruby
|
247
|
+
s = SaleOrder.find(2)
|
248
|
+
s.wkf_action('cancel')
|
249
|
+
s.state
|
250
|
+
#=> 'cancel'
|
251
|
+
```
|
229
252
|
|
230
253
|
On Change methods:
|
231
254
|
|
@@ -236,9 +259,11 @@ you need to explicitely tell the on_change name, the parameter name that changed
|
|
236
259
|
enfore the on_change syntax (looking at the OpenERP model code or view or XML/RPC logs will help you to find out). But
|
237
260
|
ultimately it works:
|
238
261
|
|
239
|
-
|
240
|
-
|
241
|
-
|
262
|
+
```ruby
|
263
|
+
l = SaleOrderLine.new
|
264
|
+
l.on_change('product_id_change', :product_id, 20, 1, 20, 1, false, 1, false, false, 7, 'en_US', true, false, false, false)
|
265
|
+
#=> #<SaleOrderLine:0x7f76118b4348 @prefix_options={}, @relations={"product_uos"=>false, "product_id"=>20, "product_uom"=>1, "tax_id"=>[]}, @loaded_relations={}, @attributes={"name"=>"[TOW1] ATX Mid-size Tower", "product_uos_qty"=>1, "delay"=>1.0, "price_unit"=>37.5, "type"=>"make_to_stock", "th_weight"=>0}>
|
266
|
+
```
|
242
267
|
Notice that it reloads the Objects attrs and print warning message accordingly
|
243
268
|
|
244
269
|
|
@@ -247,12 +272,14 @@ On the fly one2many object graph update/creation:
|
|
247
272
|
Just like the OpenERP GTK client (and unlike the web client), in OOOR you can pass create/update
|
248
273
|
one2many relation in place directly. For instance:
|
249
274
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
275
|
+
```ruby
|
276
|
+
so = SaleOrder.new
|
277
|
+
so.on_change('onchange_partner_id', :partner_id, 1, 1, false) #auto-complete the address and other data based on the partner
|
278
|
+
so.order_line = [SaleOrderLine.new(:name => 'sl1', :product_id => 1, :price_unit => 42, :product_uom => 1)] #create one order line
|
279
|
+
so.save
|
280
|
+
so.amount_total
|
281
|
+
#=> 42.0
|
282
|
+
```
|
256
283
|
|
257
284
|
|
258
285
|
Call aribtrary method:
|
@@ -261,22 +288,27 @@ Call aribtrary method:
|
|
261
288
|
$ or object.call(method_name, args*) #were args is an aribtrary list of arguments
|
262
289
|
|
263
290
|
Class methods from are osv.py/orm.py proxied to OpenERP directly (as the web client does):
|
264
|
-
|
265
|
-
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
ResPartner.name_search('ax', [], 'ilike', {})
|
294
|
+
ProductProduct.fields_view_get(132, 'tree', {})
|
295
|
+
```
|
266
296
|
|
267
297
|
|
268
|
-
Call old style wizards:
|
298
|
+
Call old style wizards (OpenERP v5):
|
269
299
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
300
|
+
```ruby
|
301
|
+
inv = AccountInvoice.find(4)
|
302
|
+
#in case the inv.state is 'draft', do inv.wkf_action('invoice_open')
|
303
|
+
wizard = inv.old_wizard_step('account.invoice.pay') #tip: you can inspect the wizard fields, arch and datas
|
304
|
+
wizard.reconcile({:journal_id => 6, :name =>"from_rails"}) #if you want to pay all; will give you a reloaded invoice
|
305
|
+
inv.state
|
306
|
+
#=> "paid"
|
307
|
+
#or if you want a payment with a write off:
|
308
|
+
wizard.writeoff_check({"amount" => 12, "journal_id" => 6, "name" =>'from_rails'}) #use the button name as the wizard method
|
309
|
+
wizard.reconcile({required missing write off fields...}) #will give you a reloaded invoice because state is 'end'
|
310
|
+
#TODO test and document new osv_memory wizards API
|
311
|
+
```
|
280
312
|
|
281
313
|
|
282
314
|
Absolute OpenERP ids aka ir_model_data:
|
@@ -286,39 +318,48 @@ We are here speaking about the string id of the XML or CSV records, eventually p
|
|
286
318
|
Using those ids rather than the SQL ids is a good idea to avoid relying on a particular installation.
|
287
319
|
In OOOR, you can both retrieve one or several records using those ids, like for instance:
|
288
320
|
|
289
|
-
|
321
|
+
```ruby
|
322
|
+
ProductCategory.find('product.product_category_3')
|
323
|
+
```
|
290
324
|
|
291
325
|
Notice that the 'product.' module prefix is optional here but important if you have similar ids in different module scopes.
|
292
326
|
You can also create a resource and it's ir_model_data record alltogether using the ir_mode_data_id param:
|
293
327
|
|
294
|
-
|
295
|
-
|
328
|
+
```ruby
|
329
|
+
ProductCategory.create(:name => 'rails_categ', :ir_model_data_id =>['product', 'categ_x']) #1st tab element is the module, 2nd the id in the module
|
330
|
+
```
|
296
331
|
|
297
332
|
Obtain report binary data:
|
298
333
|
|
299
334
|
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.
|
300
335
|
Example:
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
336
|
+
|
337
|
+
```ruby
|
338
|
+
inv = AccountInvoice.find(3)
|
339
|
+
report = inv.get_report_data('account.invoice') #account.invoice is the service name defined in Invoices report
|
340
|
+
#Save the report to a file
|
341
|
+
#report[1] contains the file extension and report[0] contains the binary data of the report encoded in base64
|
342
|
+
File.open("invoice_report.#{report[1]}", "w") {|f| f.write(Base64.decode64(report[0]))}
|
343
|
+
```
|
307
344
|
|
308
345
|
Change logged user:
|
309
346
|
|
310
347
|
An Ooor client can have a global user logged in, to change it:
|
311
348
|
|
312
|
-
|
313
|
-
|
314
|
-
|
349
|
+
```ruby
|
350
|
+
Ooor.global_login('demo', 'demo')
|
351
|
+
s = SaleOrder.find(2)
|
352
|
+
#=> 'Access denied error'
|
353
|
+
```
|
315
354
|
|
316
355
|
Instead, every Ooor business objects can also belong to some specific user. To achieve that, generate your object passing
|
317
356
|
proper :user_id and :password parameters inside the context of the method creating the object (typically a find).
|
318
357
|
Notice that methods invoked on an objet use the same credentials as the business objects.
|
319
358
|
Objects generated by this object (by a call to an association for instance) will also have the same credentials.
|
320
359
|
|
321
|
-
|
360
|
+
```ruby
|
361
|
+
p = ProductProduct.find(1, :context => {:user_id=>3, :password=>'test'})
|
362
|
+
```
|
322
363
|
|
323
364
|
This is tipycally the system you will use in a Ruby (Rails or not) web application.
|
324
365
|
|
@@ -327,8 +368,10 @@ Change log level:
|
|
327
368
|
By default the log level is very verbose (debug level) to help newcomers to jumpstart.
|
328
369
|
However you might want to change that. 2 solutions:
|
329
370
|
|
330
|
-
|
331
|
-
|
371
|
+
```ruby
|
372
|
+
Ooor.logger.level = 1 #available levels are those of the standard Ruby Logger class: 0 debug, 1 info, 2 error
|
373
|
+
```
|
374
|
+
In the config yaml file or hash, set the :log_level parameter
|
332
375
|
|
333
376
|
|
334
377
|
[Drawing OpenERP UML diagrams with OOOR](http://wiki.github.com/rvalyi/ooor/drawing-openerp-uml-diagrams-with-ooor)
|
data/bin/ooor
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
puts "*** OOOR - OpenObject on Ruby! Published under the
|
3
|
+
puts "*** OOOR - OpenObject on Ruby! Published under the MIT license by Akretion.com ***"
|
4
4
|
|
5
5
|
require 'irb'
|
6
6
|
require 'rubygems'
|
@@ -9,7 +9,7 @@ require 'irb/completion'
|
|
9
9
|
|
10
10
|
unless ARGV.empty?
|
11
11
|
username = ARGV[0].split(".")[0]
|
12
|
-
database = ARGV[0].split(".")[1].split("@")[0]
|
12
|
+
database = ARGV[0].split(".")[1..100].join(".").split("@")[0]
|
13
13
|
if ARGV[0].index("@")
|
14
14
|
base_url = ARGV[0].split("@")[1]
|
15
15
|
else
|
@@ -29,7 +29,9 @@ unless ARGV.empty?
|
|
29
29
|
password = ARGV[1]
|
30
30
|
else
|
31
31
|
puts "password?"
|
32
|
+
system "stty -echo"
|
32
33
|
password = $stdin.gets.chomp!
|
34
|
+
system "stty echo"
|
33
35
|
end
|
34
36
|
|
35
37
|
if ARGV[1] == "-s" || ARGV[2] == "-s" #secure mode
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# OOOR: OpenObject On Ruby
|
2
|
+
# Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
|
3
|
+
# Author: Akretion: Raphaël Valyi: CampToCamp: Nicolas Bessi, Joel Grand-Guillaume
|
4
|
+
# Licensed under the MIT license, see MIT-LICENSE file
|
5
|
+
|
6
|
+
Ooor.xtend('ir.module.module') do
|
7
|
+
|
8
|
+
##########################################################################
|
9
|
+
# Get recursively the whole list of modules dependencies
|
10
|
+
# for a list of modules.
|
11
|
+
# Do not add the module if it already exists in the input list
|
12
|
+
# Input :
|
13
|
+
# - modules : A [] of valid IrModuleModule instances with dependencies_id attribute
|
14
|
+
# Return
|
15
|
+
# - [] of dependencies
|
16
|
+
# Usage Example:
|
17
|
+
# dependency_modules = get_dependencies(modules)
|
18
|
+
def self.get_dependencies(modules)
|
19
|
+
dependency_modules = []
|
20
|
+
modules.select { |m| m.dependencies_id }.each do |mod|
|
21
|
+
mod.dependencies_id.each do |dep|
|
22
|
+
dep_module = IrModuleModule.find(:first,
|
23
|
+
:domain => [['name', '=', dep.name]],
|
24
|
+
:fields => ['id', 'state', 'dependencies_id'])
|
25
|
+
if dep_module.nil?
|
26
|
+
raise RuntimeError, "#{dep.name} not found"
|
27
|
+
end
|
28
|
+
dependency_modules << dep_module unless (modules + dependency_modules).map { |m| m.id }.include? dep_module.id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
dependency_modules.concat(get_dependencies(dependency_modules)) if dependency_modules.count > 0
|
32
|
+
dependency_modules.uniq { |m| m.id }
|
33
|
+
end
|
34
|
+
|
35
|
+
##########################################################################
|
36
|
+
# Run the upgrade wizard in order to install the required
|
37
|
+
# modules. Upgrade installed modules as well.
|
38
|
+
# Input :
|
39
|
+
# - modules : A [] of valid IrModuleModule instance
|
40
|
+
# Return
|
41
|
+
# - True
|
42
|
+
# Usage Example:
|
43
|
+
# res = IrModuleModule.install_modules(@openerp, modules)
|
44
|
+
def self.install_modules(openerp, modules, dependencies=false)
|
45
|
+
res = true
|
46
|
+
if dependencies
|
47
|
+
dependency_modules = get_dependencies(modules)
|
48
|
+
modules.concat(dependency_modules) if dependency_modules
|
49
|
+
end
|
50
|
+
modules_toinstall_ids = []
|
51
|
+
modules_toupgrade_ids = []
|
52
|
+
# If not installed, do it. Otherwise update it
|
53
|
+
modules.each do |m|
|
54
|
+
if m.state == 'uninstalled'
|
55
|
+
m.state = 'to install'
|
56
|
+
m.save
|
57
|
+
modules_toinstall_ids << m.id
|
58
|
+
elsif m.state == 'installed'
|
59
|
+
m.state = 'to upgrade'
|
60
|
+
m.save
|
61
|
+
modules_toupgrade_ids << m.id
|
62
|
+
elsif m.state == 'to install'
|
63
|
+
modules_toinstall_ids << m.id
|
64
|
+
elsif m.state == 'to upgrade'
|
65
|
+
modules_toupgrade_ids << m.id
|
66
|
+
end
|
67
|
+
end
|
68
|
+
#First installed required modules, then upgrade the others
|
69
|
+
upgrade = BaseModuleUpgrade.create()
|
70
|
+
upgrade.upgrade_module()
|
71
|
+
# IrModuleModule.button_install(modules_toinstall_ids)
|
72
|
+
# IrModuleModule.button_upgrade(modules_toupgrade_ids)
|
73
|
+
|
74
|
+
if res
|
75
|
+
return true
|
76
|
+
else
|
77
|
+
raise "!!! --- HELPER ERROR : install_modules was unable to install needed modules.."
|
78
|
+
end
|
79
|
+
openerp.load_models() # reload in order to have model Classes for modules installed
|
80
|
+
end
|
81
|
+
|
82
|
+
def print_uml
|
83
|
+
l = IrModelData.find(:all, :domain => {:model=>"ir.model", :module=>name})
|
84
|
+
model_names = []
|
85
|
+
l.each {|i| model_names << i.name.gsub('_', '.').gsub(/^model.report/, '').gsub(/^model./, '')}
|
86
|
+
classes = []
|
87
|
+
model_names.each {|i| begin classes << Object.const_get(IrModel.class_name_from_model_key i); rescue; end}
|
88
|
+
classes.reject! {|m| m.openerp_model.index("report")} #NOTE we would need a more robust test
|
89
|
+
begin
|
90
|
+
classes.reject! {|m| IrModel.read(m.openerp_id, ['osv_memory'])['osv_memory']}
|
91
|
+
rescue
|
92
|
+
end
|
93
|
+
classes.reject! {|m| m.openerp_model == "res.company"} if classes.size > 10
|
94
|
+
Ooor::UML.print_uml(classes, {:file_name => "#{name}_uml"})
|
95
|
+
end
|
96
|
+
|
97
|
+
def print_dependency_graph
|
98
|
+
modules = [self] + self.class.get_dependencies([self])
|
99
|
+
|
100
|
+
File.open("#{self.name}-pre.dot", 'w') do |f|
|
101
|
+
f << <<-eos
|
102
|
+
digraph DependenciesByOOOR {
|
103
|
+
fontname = "Helvetica"
|
104
|
+
fontsize = 11
|
105
|
+
label = "*** generated by OOOR by www.akretion.com ***"
|
106
|
+
node [
|
107
|
+
fontname = "Helvetica"
|
108
|
+
fontsize = 11
|
109
|
+
shape = "record"
|
110
|
+
fillcolor=orange
|
111
|
+
style="rounded,filled"
|
112
|
+
]
|
113
|
+
eos
|
114
|
+
|
115
|
+
modules.each do |m|
|
116
|
+
m.dependencies_id.each do |dep|
|
117
|
+
f << "#{m.name} -> #{dep.name};\n"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
f << "}"
|
121
|
+
end
|
122
|
+
system("tred < #{self.name}-pre.dot > #{self.name}.dot")
|
123
|
+
cmd_line2 = "dot -Tcmapx -o#{self.name}.map -Tpng -o#{self.name}.png #{self.name}.dot"
|
124
|
+
system(cmd_line2)
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
Ooor.xtend('ir.ui.menu') do
|
132
|
+
def menu_action
|
133
|
+
#TODO put in cache eventually:
|
134
|
+
action_values = self.class.ooor.const_get('ir.values').rpc_execute('get', 'action', 'tree_but_open', [['ir.ui.menu', id]], false, self.class.ooor.global_context)[0][2]#get already exists
|
135
|
+
@menu_action = self.class.ooor.const_get('ir.actions.act_window').new(action_values, []) #TODO deal with action reference instead
|
136
|
+
end
|
137
|
+
end
|