ooor 1.9.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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