ooor 1.9.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/README.md +23 -71
  2. data/Rakefile +5 -0
  3. data/bin/ooor +1 -0
  4. data/lib/ooor.rb +87 -129
  5. data/lib/ooor/associations.rb +64 -0
  6. data/lib/ooor/base.rb +218 -0
  7. data/lib/{app/models → ooor}/base64.rb +0 -0
  8. data/lib/ooor/connection.rb +37 -0
  9. data/lib/ooor/errors.rb +120 -0
  10. data/lib/ooor/field_methods.rb +153 -0
  11. data/lib/{app → ooor}/helpers/core_helpers.rb +2 -2
  12. data/lib/ooor/locale.rb +13 -0
  13. data/lib/ooor/mini_active_resource.rb +94 -0
  14. data/lib/ooor/model_registry.rb +19 -0
  15. data/lib/ooor/naming.rb +73 -0
  16. data/lib/ooor/rack.rb +114 -0
  17. data/lib/ooor/railtie.rb +41 -0
  18. data/lib/ooor/reflection.rb +537 -0
  19. data/lib/ooor/reflection_ooor.rb +92 -0
  20. data/lib/{app/models → ooor}/relation.rb +61 -22
  21. data/lib/ooor/relation/finder_methods.rb +113 -0
  22. data/lib/ooor/report.rb +53 -0
  23. data/lib/{app/models → ooor}/serialization.rb +18 -6
  24. data/lib/ooor/services.rb +133 -0
  25. data/lib/ooor/session.rb +120 -0
  26. data/lib/ooor/session_handler.rb +63 -0
  27. data/lib/ooor/transport.rb +34 -0
  28. data/lib/ooor/transport/json_client.rb +53 -0
  29. data/lib/ooor/transport/xml_rpc_client.rb +15 -0
  30. data/lib/ooor/type_casting.rb +193 -0
  31. data/lib/ooor/version.rb +8 -0
  32. data/spec/helpers/test_helper.rb +11 -0
  33. data/spec/install_nightly.sh +17 -0
  34. data/spec/ooor_spec.rb +197 -79
  35. data/spec/requirements.txt +19 -0
  36. metadata +58 -20
  37. data/lib/app/models/client_xmlrpc.rb +0 -34
  38. data/lib/app/models/open_object_resource.rb +0 -486
  39. data/lib/app/models/services.rb +0 -47
  40. data/lib/app/models/type_casting.rb +0 -134
  41. data/lib/app/models/uml.rb +0 -210
  42. data/lib/app/ui/action_window.rb +0 -96
  43. data/lib/app/ui/client_base.rb +0 -36
  44. data/lib/app/ui/form_model.rb +0 -88
  45. data/ooor.yml +0 -27
@@ -0,0 +1,8 @@
1
+ module Ooor
2
+ MAJOR = 2
3
+ MINOR = 0
4
+ TINY = 0
5
+ PRE = nil
6
+
7
+ VERSION = [MAJOR, MINOR, TINY].compact.join('.')
8
+ end
@@ -0,0 +1,11 @@
1
+ Ooor.xtend('ir.module.module') do
2
+
3
+ def self.say_hello()
4
+ return "Hello"
5
+ end
6
+
7
+ def say_name()
8
+ return self.name
9
+ end
10
+
11
+ end
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ # Install the nightly version of OpenERP
3
+ sudo apt-get -ym install python-dateutil python-docutils python-feedparser python-gdata python-jinja2 python-ldap python-lxml python-mako python-mock python-openid python-psycopg2 python-psutil python-pybabel python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-tz python-unittest2 python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt python-yaml python-zsi python-imaging
4
+ wget http://nightly.openerp.com/7.0/nightly/src/openerp-7.0-latest.tar.gz
5
+ mkdir -p src
6
+ tar -xf openerp-7.0-latest.tar.gz -C src
7
+
8
+ for f in ./src/*
9
+ do
10
+ echo "$f" | grep -Eq '^\./abc.[0-9]+$' && continue
11
+ echo "Something with $f here"
12
+ done
13
+
14
+ mv $f openerp
15
+ rm -rf ./src
16
+ cd openerp
17
+ python setup.py --quiet install
data/spec/ooor_spec.rb CHANGED
@@ -3,13 +3,17 @@
3
3
  # Author: Raphaël Valyi
4
4
  # Licensed under the MIT license, see MIT-LICENSE file
5
5
 
6
+ if ENV["CI"]
7
+ require 'coveralls'
8
+ Coveralls.wear!
9
+ end
6
10
  require File.dirname(__FILE__) + '/../lib/ooor'
7
11
 
8
12
  #RSpec executable specification; see http://rspec.info/ for more information.
9
13
  #Run the file with the rspec command from the rspec gem
10
14
  describe Ooor do
11
15
  before(:all) do
12
- @url = 'http://localhost:8169/xmlrpc'
16
+ @url = 'http://localhost:8069/xmlrpc'
13
17
  @db_password = 'admin'
14
18
  @username = 'admin'
15
19
  @password = 'admin'
@@ -18,21 +22,20 @@ describe Ooor do
18
22
  end
19
23
 
20
24
  it "should keep quiet if no database is mentioned" do
21
- @ooor.loaded_models.should be_empty
25
+ @ooor.models.should be_empty
22
26
  end
23
27
 
24
28
  it "should be able to list databases" do
25
- @ooor.list.should be_kind_of(Array)
29
+ @ooor.db.list.should be_kind_of(Array)
26
30
  end
27
31
 
28
32
  it "should be able to create a new database with demo data" do
29
- unless @ooor.list.index(@database)
30
- @ooor.create(@db_password, @database)
33
+ unless @ooor.db.list.index(@database)
34
+ @ooor.db.create(@db_password, @database)
31
35
  end
32
- @ooor.list.index(@database).should_not be_nil
36
+ @ooor.db.list.index(@database).should_not be_nil
33
37
  end
34
38
 
35
-
36
39
  describe "Configure existing database" do
37
40
  before(:all) do
38
41
  @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database)
@@ -49,40 +52,70 @@ describe Ooor do
49
52
  wizard = BaseModuleUpgrade.create
50
53
  wizard.upgrade_module
51
54
  @ooor.load_models
52
- # config5 = AccountInstaller.create(:charts => 'configurable')
53
- # config5.action_next
54
- @ooor.loaded_models.should_not be_empty
55
+ @ooor.models.keys.should_not be_empty
55
56
  end
56
57
 
57
58
  it "should be able to configure the database" do
58
- # chart_module_id = IrModuleModule.search([['category_id', '=', 'Account Charts'], ['name','=', 'l10n_fr']])[0]
59
59
  if AccountTax.search.empty?
60
60
  w1 = @ooor.const_get('account.installer').create(:charts => "configurable")
61
61
  w1.action_next
62
62
  w1 = @ooor.const_get('wizard.multi.charts.accounts').create(:charts => "configurable", :code_digits => 2)
63
63
  w1.action_next
64
- # w3 = @ooor.const_get('wizard.multi.charts.accounts').create
65
- # w3.action_create
66
64
  end
67
65
  end
68
66
  end
69
67
 
70
-
71
68
  describe "Do operations on configured database" do
72
69
  before(:all) do
73
70
  @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database,
74
- :models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
71
+ :models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu', 'ir.module.module'])
75
72
  end
76
73
 
77
74
  describe "Finders operations" do
78
-
79
75
  it "should be able to find data by id" do
80
- p = ProductProduct.find(1)
81
- p.should_not be_nil
82
- p = ProductProduct.find(:first)
83
- p.should_not be_nil
84
- l = ProductProduct.find([1,2])
85
- l.size.should == 2
76
+ product1 = ProductProduct.find(1)
77
+ expect(product1).not_to be_nil
78
+ expect(ProductProduct.find(:first).attributes).to eq product1.attributes
79
+ end
80
+
81
+ it "fetches data given an array of ids" do
82
+ products = ProductProduct.find([1,2])
83
+ products.size.should == 2
84
+ end
85
+
86
+ it "should fetches data given an implicit array of ids" do
87
+ products = ProductProduct.find(1,2)
88
+ products.size.should == 2
89
+ end
90
+
91
+ it "should fetches data even if an id is passed as a string (web usage)" do
92
+ product = ProductProduct.find("1")
93
+ product.should be_kind_of(ProductProduct)
94
+ end
95
+
96
+ it "should fetches data even with array containing string" do
97
+ products = ProductProduct.find(["1", 2])
98
+ products.size.should == 2
99
+ end
100
+
101
+ it "should fetches data even with an implicit array containing string" do
102
+ products = ProductProduct.find("1", 2)
103
+ products.size.should == 2
104
+ end
105
+
106
+ it "should accept hash domain in find" do
107
+ products = ProductProduct.find(active: true)
108
+ products.should be_kind_of(Array)
109
+ end
110
+
111
+ it "should accept array domain in find" do
112
+ products = ProductProduct.find(['active', '=', true])
113
+ products.should be_kind_of(Array)
114
+ end
115
+
116
+ it "fetches last data created last" do
117
+ last_product_id = ProductProduct.search([], 0, 1, "create_date DESC").first
118
+ expect(ProductProduct.find(:last).id).to eq last_product_id
86
119
  end
87
120
 
88
121
  it "should load required models on the fly" do
@@ -125,6 +158,13 @@ describe Ooor do
125
158
  products.should be_kind_of(Array)
126
159
  end
127
160
 
161
+ it "should support writing with a context" do
162
+ p = ProductProduct.find(1, fields: ['name'])
163
+ ProductProduct.write(1, {name: p.name}, {lang: 'en_US'})
164
+ ProductProduct.write(1, {name: p.name}, lang: 'en_US')
165
+ p.write({name: p.name}, lang: 'en_US')
166
+ end
167
+
128
168
  it "should support OpenERP search method" do
129
169
  partners = ResPartner.search([['name', 'ilike', 'a']], 0, 2)
130
170
  partners.should_not be_empty
@@ -140,7 +180,6 @@ describe Ooor do
140
180
  it "should be able to call any Class method" do
141
181
  ResPartner.name_search('ax', [], 'ilike', {}).should_not be_nil
142
182
  end
143
-
144
183
  end
145
184
 
146
185
  describe "Relations reading" do
@@ -188,21 +227,15 @@ describe Ooor do
188
227
  p.categ_id.id.should == 1
189
228
  end
190
229
 
191
- it "should support the context at object creation" do
192
- p = ProductProduct.new({:name => "testProduct1", :categ_id => 1}, false, {:lang => 'en_US', :user_id=>1, :password => 'admin'})
193
- p.object_session[:context][:lang] .should == 'en_US'
194
- p.object_session[:user_id].should == 1
195
- p.object_session[:password].should == "admin"
196
- p.save
197
- end
198
-
199
- it "should support context when instanciating collections" do
200
- products = ProductProduct.find([1, 2, 3], :context => {:lang => 'en_US', :user_id=>1, :password => 'admin'})
201
- p = products[0]
202
- p.object_session[:context][:lang].should == 'en_US'
203
- p.object_session[:user_id].should == 1
204
- p.object_session[:password].should == "admin"
205
- p.save
230
+ it "should support read on new objects" do
231
+ u = ResUsers.new({name: "joe", login: "joe"})
232
+ u.id.should be_nil
233
+ u.name.should == "joe"
234
+ u.email.should == nil
235
+ u.save
236
+ u.id.should_not be_nil
237
+ u.name.should == "joe"
238
+ u.destroy
206
239
  end
207
240
 
208
241
  it "should be able to create an order" do
@@ -286,9 +319,67 @@ describe Ooor do
286
319
  end
287
320
  end
288
321
 
289
- describe "Old wizard management" do
322
+ describe "Rails associations methods" do
323
+ it "should read m2o id with an extra _id suffix" do
324
+ p = ProductProduct.find(1)
325
+ p.categ_id_id.should be_kind_of(Integer)
326
+ end
327
+
328
+ it "should read o2m with an extra _ids suffix" do
329
+ so = SaleOrder.find :first
330
+ so.order_line_ids.should be_kind_of(Array)
331
+ end
332
+
333
+ it "should read m2m with an extra _ids suffix" do
334
+ p = ProductProduct.find(1)
335
+ p.taxes_id_ids.should be_kind_of(Array)
336
+ end
337
+
338
+ it "should support Rails nested attributes" do
339
+ so = SaleOrder.find :first
340
+ so.respond_to?(:order_line_attributes).should be_true
341
+ so.respond_to?(:order_line_attributes=).should be_true
342
+ end
343
+
344
+ it "should be able to call build upon a o2m association" do
345
+ so = SaleOrder.find :first
346
+ so.order_line.build().should be_kind_of(SaleOrderLine)
347
+ end
348
+ end
349
+
350
+ describe "Fields validations" do
351
+ it "should point to invalid fields" do
352
+ p = ProductProduct.find :first
353
+ p.ean13 = 'invalid_ean'
354
+ p.save.should == false
355
+ p.errors.messages[:ean13].should_not be_nil
356
+ end
357
+ end
358
+
359
+ describe "ARel emulation" do
360
+ it "should have an 'all' method" do
361
+ ResUsers.all.should be_kind_of(Array)
362
+ end
363
+
364
+ it "should be ready for Kaminari pagination via ARel scoping" do
365
+ num = 2
366
+ default_per_page = 5
367
+ collection = ProductProduct.limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1))
368
+ collection.all(fields:['name']).should be_kind_of(Array)
369
+ collection.all.size.should == 5
370
+ end
371
+ end
372
+
373
+ describe "report support" do
374
+ it "should print reports" do
375
+ base_id = IrModuleModule.search(name:'base')[0]
376
+ IrModuleModule.get_report_data("ir.module.reference", [base_id], 'pdf', {}).should be_kind_of(Array)
377
+ end
378
+ end
379
+
380
+ describe "wizard management" do
290
381
  it "should be possible to pay an invoice in one step" do
291
- inv = AccountInvoice.find(:last).copy() #creates a draft invoice
382
+ inv = AccountInvoice.find(:first).copy() # creates a draft invoice
292
383
  inv.state.should == "draft"
293
384
  inv.wkf_action('invoice_open')
294
385
  inv.state.should == "open"
@@ -297,10 +388,7 @@ describe Ooor do
297
388
  voucher.save
298
389
  voucher.wkf_action 'proforma_voucher'
299
390
 
300
- #wizard = inv.old_wizard_step('account.invoice.pay') #tip: you can inspect the wizard fields, arch and datas
301
- #inv = wizard.reconcile({:journal_id => 6, :name =>"from_rails"}) #if you want to pay all; will give you a reloaded invoice
302
391
  inv.reload
303
- # inv.state.should == "paid" #TODO!!
304
392
  end
305
393
 
306
394
  it "should be possible to call resource actions and workflow actions" do
@@ -317,10 +405,6 @@ describe Ooor do
317
405
  end
318
406
  end
319
407
 
320
- describe "New style wizards" do
321
- #already tested, see database configuration test
322
- end
323
-
324
408
  describe "Delete resources" do
325
409
  it "should be able to call unlink" do
326
410
  ids = ProductProduct.search([['name', 'ilike', 'testProduct']])
@@ -338,58 +422,59 @@ describe Ooor do
338
422
 
339
423
  end
340
424
 
341
-
342
- describe "Offer Web Client core features" do
425
+ describe "Object context abilities" do
343
426
  before(:all) do
344
- @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database,
345
- :models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
346
- end
347
-
348
- it "should find the default user action" do
349
- @ooor.get_init_menu(1)
427
+ @ooor = Ooor.new(:url => @url, :database => @database)
350
428
  end
351
429
 
352
- it "should be able to find the sub-menus of a menu" do
353
- menu = IrUiMenu.find(:first, :domain => [['name', '=', 'Partners'], ['parent_id', '!=', false]])
354
- menu.child_id.each do |sub_menu|
355
- sub_menu.should be_kind_of(IrUiMenu)
356
- end
430
+ it "should support context when instanciating collections" do
431
+ @ooor.const_get('product.product')
432
+ products = ProductProduct.find([1, 2, 3], :context => {:lang => 'en_US'})
433
+ p = products[0]
434
+ p.object_session[:lang].should == 'en_US'
435
+ p.save
357
436
  end
437
+ end
358
438
 
359
- it "should retrieve the action of a menu" do
360
- Ooor::ActionWindow.from_menu(IrUiMenu.find(:first, :domain => [['name', '=', 'Customers']])).search.should be_kind_of Array
361
- end
439
+ describe "Web SEO utilities" do
440
+ include Ooor
362
441
 
363
- it "should be able to open a list view of a menu action" do
364
- Ooor::ActionWindow.from_menu(IrUiMenu.find(:first, :domain => [['name', '=', 'Customers']])).get_fields 'tree'
442
+ it "should support model aliases" do
443
+ Ooor.session_handler.reset!() # alias isn't part of the connection spec, we don't want connectio reuse here
444
+ with_ooor_session(:url => @url, :database => @database, :username => @username, :password => @password, :aliases => {en_US: {products: 'product.product'}}, :param_keys => {'product.product' => 'name'}) do |session|
445
+ session['products'].search().should be_kind_of(Array)
446
+ end
365
447
  end
366
448
 
367
- it "should be able to open a form view of a menu action" do
368
- Ooor::ActionWindow.from_menu(IrUiMenu.find(:first, :domain => [['name', '=', 'Customers']])).get_fields 'form'
449
+ it "should find by permalink" do
450
+ Ooor.session_handler.reset!() # alias isn't part of the connection spec, we don't want connectio reuse here
451
+ with_ooor_session(:url => @url, :database => @database, :username => @username, :password => @password, :aliases => {en_US: {products: 'product.product'}}, :param_keys => {'product.product' => 'name'}) do |session|
452
+ lang = Ooor::Locale.to_erp_locale('en')
453
+ session['products'].find_by_permalink('Service', context: {'lang' => lang}, fields: ['name']).should be_kind_of(Ooor::Base)
454
+ end
369
455
  end
370
456
  end
371
457
 
372
-
373
- describe "UML features" do
458
+ describe "Ative-Record like Reflection" do
374
459
  before(:all) do
375
- @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database,
376
- :models => ['res.user', 'res.partner', 'product.product', 'sale.order', 'account.invoice', 'product.category', 'stock.move', 'ir.ui.menu'])
460
+ @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database, :models => ['product.product'], :reload => true)
377
461
  end
378
462
 
379
- it "should be able to draw the UML of any class" do
380
- SaleOrder.print_uml.should be_true
463
+ it "should test correct class attributes" do
464
+ object = Ooor::Reflection::AssociationReflection.new(:test, :people, {}, nil)
465
+ object.name.should == :people
466
+ object.macro.should == :test
467
+ object.options.should == {}
381
468
  end
382
469
 
383
- it "should be able to draw the UML of several classes" do
384
- Ooor::UML.print_uml([SaleOrder, SaleShop]).should be_true
470
+ it "should test correct class name matching wit class name" do
471
+ object = Ooor::Reflection::AssociationReflection.new(:test, 'product_product', {class_name: 'product.product'}, nil)
472
+ object.connection = @ooor
473
+ object.klass.should == ProductProduct
385
474
  end
386
475
 
387
- it "should accept rendering options" do
388
- SaleOrder.print_uml({:detailed => true}).should be_true
389
- end
390
476
  end
391
477
 
392
-
393
478
  describe "Multi-instance and class name scoping" do
394
479
  before(:all) do
395
480
  @ooor1 = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database, :scope_prefix => 'OE1', :models => ['res.partner', 'product.product'], :reload => true)
@@ -407,6 +492,39 @@ describe Ooor do
407
492
  end
408
493
  end
409
494
 
495
+ describe "Multi-sessions mode" do
496
+ include Ooor
497
+ it "should allow with_session" do
498
+ with_ooor_session(:url => @url, :username => @username, :password => @password, :database => @database) do |session|
499
+ session['res.users'].search().should be_kind_of(Array)
500
+ new_user = session['res.users'].create(name: 'User created by OOOR as admin', login: 'ooor1')
501
+ new_user.destroy
502
+ end
503
+
504
+ with_ooor_session(:url => @url, :username => 'demo', :password => 'demo', :database => @database) do |session|
505
+ h = session['res.users'].read([1], ["password"])
506
+ h[0]['password'].should == "********"
507
+ end
508
+
509
+ with_ooor_default_session(:url => @url, :username => @username, :password => @password, :database => @database) do |session|
510
+ session['res.users'].search().should be_kind_of(Array)
511
+ end
512
+ end
513
+ end
514
+
515
+
516
+ describe "Multi-format serialization" do
517
+ before(:all) do
518
+ @ooor = Ooor.new(:url => @url, :username => @username, :password => @password, :database => @database)
519
+ end
520
+
521
+ it "should serialize in json" do
522
+ ProductProduct.find(1).as_json
523
+ end
524
+ it "should serialize in json" do
525
+ ProductProduct.find(1).to_xml
526
+ end
527
+ end
410
528
 
411
529
  describe "Ruby OpenERP extensions" do
412
530
  before(:all) do
@@ -0,0 +1,19 @@
1
+ pillow
2
+ docutils
3
+ psutil
4
+ pytz
5
+ psycopg2
6
+ reportlab
7
+ lxml
8
+ Mako
9
+ --find-links=http://download.gna.org/pychart/
10
+ PyChart
11
+ vobject
12
+ Babel
13
+ simplejson
14
+ python-dateutil
15
+ python-openid
16
+ PyYaml
17
+ werkzeug
18
+ unittest2
19
+ mock