decidim-odoo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +169 -0
  4. data/Rakefile +43 -0
  5. data/app/commands/decidim/odoo/sync_user.rb +57 -0
  6. data/app/controllers/concerns/decidim/odoo/admin/members/filterable.rb +33 -0
  7. data/app/controllers/decidim/odoo/admin/members_controller.rb +33 -0
  8. data/app/forms/decidim/odoo/verifications/odoo_member.rb +53 -0
  9. data/app/helpers/decidim/odoo/admin/odoo_helper.rb +21 -0
  10. data/app/jobs/decidim/odoo/auto_verification_job.rb +46 -0
  11. data/app/jobs/decidim/odoo/omniauth_user_sync_job.rb +24 -0
  12. data/app/jobs/decidim/odoo/sync_users_job.rb +19 -0
  13. data/app/models/concerns/decidim/odoo/user_override.rb +21 -0
  14. data/app/models/decidim/odoo/user.rb +18 -0
  15. data/app/packs/entrypoints/decidim_odoo.js +2 -0
  16. data/app/packs/images/odoo_logo.svg +4 -0
  17. data/app/views/decidim/odoo/admin/members/index.html.erb +58 -0
  18. data/config/assets.rb +8 -0
  19. data/config/i18n-tasks.yml +8 -0
  20. data/config/locales/en.yml +41 -0
  21. data/db/migrate/20230713143501_create_decidim_odoo_users.rb +20 -0
  22. data/lib/decidim/odoo/admin.rb +10 -0
  23. data/lib/decidim/odoo/admin_engine.rb +49 -0
  24. data/lib/decidim/odoo/api/base/base_query.rb +28 -0
  25. data/lib/decidim/odoo/api/base/request.rb +48 -0
  26. data/lib/decidim/odoo/api/find_partner.rb +21 -0
  27. data/lib/decidim/odoo/api/find_partner_by_vat.rb +21 -0
  28. data/lib/decidim/odoo/api.rb +25 -0
  29. data/lib/decidim/odoo/engine.rb +48 -0
  30. data/lib/decidim/odoo/test/factories.rb +22 -0
  31. data/lib/decidim/odoo/test/shared_contexts.rb +18 -0
  32. data/lib/decidim/odoo/version.rb +10 -0
  33. data/lib/decidim/odoo.rb +42 -0
  34. data/lib/generators/decidim/odoo/install_generator.rb +47 -0
  35. data/lib/generators/decidim/odoo/templates/development_odoo_config.rb +21 -0
  36. data/lib/generators/decidim/odoo/templates/test_odoo_config.rb +20 -0
  37. data/lib/omniauth/strategies/odoo_keycloak.rb +25 -0
  38. data/lib/tasks/decidim_odoo.rake +16 -0
  39. metadata +135 -0
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimOdooUsers < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :decidim_odoo_users do |t|
6
+ t.references :decidim_organization, null: false, foreign_key: { to_table: :decidim_organizations }, index: { name: :index_odoo_users_on_decidim_organization_id }
7
+ t.references :decidim_user, null: false, foreign_key: { to_table: :decidim_users }, index: { name: :index_odoo_users_on_decidim_user_id }
8
+
9
+ t.integer :odoo_user_id
10
+ t.string :ref
11
+ t.boolean :coop_candidate, default: false
12
+ t.boolean :member, default: false
13
+
14
+ t.timestamps
15
+
16
+ t.index %w(decidim_organization_id odoo_user_id), name: "index_unique_odoo_user_and_organization", unique: true
17
+ t.index %w(decidim_organization_id ref), name: "index_unique_ref_and_organization", unique: true
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ # This module contains all the domain logic associated to the decidim-odoo
6
+ # module admin panel.
7
+ module Admin
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ # This is the engine that runs on the admin interface of decidim-odoo.
6
+ class AdminEngine < ::Rails::Engine
7
+ isolate_namespace Decidim::Odoo::Admin
8
+
9
+ paths["db/migrate"] = nil
10
+ paths["lib/tasks"] = nil
11
+
12
+ routes do
13
+ resources :members, only: [:index] do
14
+ collection do
15
+ get :sync
16
+ end
17
+ end
18
+
19
+ root to: "members#index"
20
+ end
21
+
22
+ initializer "decidim_odoo.webpacker.assets_path" do
23
+ Decidim.register_assets_path File.expand_path("app/packs", root)
24
+ end
25
+
26
+ initializer "decidim.odoo.mount_admin_engine" do
27
+ Decidim::Core::Engine.routes do
28
+ mount Decidim::Odoo::AdminEngine, at: "/admin/odoo", as: "decidim_odoo_admin"
29
+ end
30
+ end
31
+
32
+ initializer "decidim.odoo.admin_menu" do
33
+ Decidim.menu :admin_menu do |menu|
34
+ menu.add_item :odoo,
35
+ "Odoo",
36
+ decidim_odoo_admin.members_path,
37
+ icon_name: "people",
38
+ position: 5.75,
39
+ active: is_active_link?(decidim_odoo_admin.members_path, :inclusive),
40
+ if: defined?(current_user) && current_user&.read_attribute("admin")
41
+ end
42
+ end
43
+
44
+ def load_seed
45
+ nil
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ module Api
6
+ module Base
7
+ class BaseQuery
8
+ attr_reader :result, :request
9
+
10
+ def response
11
+ @request.response
12
+ end
13
+
14
+ protected
15
+
16
+ def parsed_response
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def store_result
21
+ @result = parsed_response
22
+ @result = @result.deep_symbolize_keys if @result.is_a? Hash
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ module Api
6
+ module Base
7
+ class Request
8
+ def initialize(verify_ssl: true)
9
+ @verify_ssl = verify_ssl
10
+ end
11
+
12
+ attr_accessor :response, :body
13
+
14
+ %w(get post).each do |method|
15
+ define_singleton_method(method) do |path, params: {}, headers: {}, verify_ssl: true|
16
+ instance = Request.new(verify_ssl: verify_ssl)
17
+ response = instance.connection.public_send(method, instance.url(path)) do |request|
18
+ request.params = instance.base_params.merge(params)
19
+ request.headers = instance.base_headers.merge(headers)
20
+ end
21
+
22
+ raise Decidim::Odoo::Error, response.reason_phrase unless response.success?
23
+
24
+ instance.response = JSON.parse(response.body)
25
+ instance
26
+ end
27
+ end
28
+
29
+ def connection
30
+ @connection ||= Faraday.new(ssl: { verify: @verify_ssl })
31
+ end
32
+
33
+ def url(path)
34
+ "#{Decidim::Odoo::Api.base_url}/#{path}"
35
+ end
36
+
37
+ def base_params
38
+ {}
39
+ end
40
+
41
+ def base_headers
42
+ { "api-key" => Decidim::Odoo::Api.api_key }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ module Api
6
+ class FindPartner < Base::BaseQuery
7
+ def initialize(ref)
8
+ @request = Base::Request.get("partner/#{ref}")
9
+
10
+ store_result
11
+ end
12
+
13
+ protected
14
+
15
+ def parsed_response
16
+ response
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Odoo
5
+ module Api
6
+ class FindPartnerByVat < Base::BaseQuery
7
+ def initialize(vat)
8
+ @request = Base::Request.get("partner", params: { vat: vat })
9
+
10
+ store_result
11
+ end
12
+
13
+ protected
14
+
15
+ def parsed_response
16
+ response
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "api/base/base_query"
4
+ require_relative "api/base/request"
5
+ require_relative "api/find_partner"
6
+ require_relative "api/find_partner_by_vat"
7
+
8
+ module Decidim
9
+ module Odoo
10
+ # This namespace holds the logic to connect to the Odoo REST API.
11
+ module Api
12
+ def self.config
13
+ Decidim::Odoo.api
14
+ end
15
+
16
+ def self.api_key
17
+ config[:api_key]
18
+ end
19
+
20
+ def self.base_url
21
+ config[:base_url]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "omniauth/strategies/odoo_keycloak"
4
+
5
+ module Decidim
6
+ module Odoo
7
+ # This is the engine that runs on the public interface of odoo.
8
+ class Engine < ::Rails::Engine
9
+ isolate_namespace Decidim::Odoo
10
+
11
+ config.to_prepare do
12
+ Decidim::User.include(Decidim::Odoo::UserOverride)
13
+ end
14
+
15
+ initializer "decidim_odoo.omniauth" do
16
+ next unless Decidim::Odoo.keycloak_omniauth && Decidim::Odoo.keycloak_omniauth[:client_id]
17
+
18
+ Rails.application.config.middleware.use OmniAuth::Builder do
19
+ provider :odoo_keycloak, Decidim::Odoo.keycloak_omniauth[:client_id], Decidim::Odoo.keycloak_omniauth[:client_secret],
20
+ client_options: Decidim::Odoo.keycloak_omniauth[:client_options]
21
+ end
22
+ end
23
+
24
+ initializer "decidim_odoo.user_sync" do
25
+ ActiveSupport::Notifications.subscribe "decidim.user.omniauth_registration" do |_name, data|
26
+ Decidim::Odoo::OmniauthUserSyncJob.perform_later(data) if data[:provider] == Decidim::Odoo::OMNIAUTH_PROVIDER_NAME
27
+ end
28
+ ActiveSupport::Notifications.subscribe "decidim.odoo.user.updated" do |_name, data|
29
+ Decidim::Odoo::AutoVerificationJob.perform_later(data)
30
+ end
31
+ end
32
+
33
+ initializer "decidim_odoo.authorizations" do
34
+ next unless Decidim::Odoo.authorizations
35
+
36
+ if Decidim::Odoo.authorizations.include?(:odoo_member)
37
+ Decidim::Verifications.register_workflow(:odoo_member) do |workflow|
38
+ workflow.form = "Decidim::Odoo::Verifications::OdooMember"
39
+ end
40
+ end
41
+ end
42
+
43
+ initializer "decidim_odoo.webpacker.assets_path" do
44
+ Decidim.register_assets_path File.expand_path("app/packs", root)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/core/test/factories"
4
+
5
+ module Decidim::Odoo::Faker
6
+ class << self
7
+ def vat
8
+ "ES#{Faker::IDNumber.spanish_citizen_number.tr("-", "")}"
9
+ end
10
+ end
11
+ end
12
+
13
+ FactoryBot.define do
14
+ factory :odoo_user, class: "Decidim::Odoo::User" do
15
+ user
16
+ organization { user.organization }
17
+ odoo_user_id { Faker::Number.between(from: 1, to: 100_000) }
18
+ ref { Faker::Number.between(from: 1, to: 100_000).to_s }
19
+ coop_candidate { false }
20
+ member { false }
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_context "with stubs example api" do
4
+ let(:http_method) { :get }
5
+ let(:http_status) { 200 }
6
+ let(:data) { { "foo" => "bar" } }
7
+ let(:params) { {} }
8
+
9
+ before do
10
+ stub_request(http_method, /api\.example\.org/).to_return(status: http_status, body: data.to_json, headers: {})
11
+ end
12
+ end
13
+
14
+ shared_examples_for "no authorization is created" do
15
+ it "does not create an authorization" do
16
+ expect { subject.perform_now(params) }.not_to change(Decidim::Authorization, :count)
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This holds the decidim-meetings version.
5
+ module Odoo
6
+ VERSION = "0.1.0"
7
+ DECIDIM_VERSION = "0.26.7"
8
+ COMPAT_DECIDIM_VERSION = [">= 0.25.0", "< 0.27"].freeze
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/odoo/admin"
4
+ require "decidim/odoo/admin_engine"
5
+ require "decidim/odoo/api"
6
+ require "decidim/odoo/engine"
7
+
8
+ module Decidim
9
+ # This namespace holds the logic of the `Odoo` component. This component
10
+ # allows users to create odoo in a participatory space.
11
+ module Odoo
12
+ include ActiveSupport::Configurable
13
+
14
+ OMNIAUTH_PROVIDER_NAME = "odoo_keycloak"
15
+
16
+ config_accessor :api do
17
+ {
18
+ base_url: ENV["ODOO_API_BASE_URL"].presence,
19
+ api_key: ENV["ODOO_API_API_KEY"].presence
20
+ }
21
+ end
22
+
23
+ config_accessor :keycloak_omniauth do
24
+ {
25
+ enabled: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_ID"].present?,
26
+ client_id: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_ID"].presence,
27
+ client_secret: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_SECRET"].presence,
28
+ client_options: {
29
+ site: ENV["OMNIAUTH_ODOO_KEYCLOAK_SITE"].presence,
30
+ realm: ENV["OMNIAUTH_ODOO_KEYCLOAK_REALM"].presence
31
+ },
32
+ icon_path: ENV["OMNIAUTH_ODOO_KEYCLOAK_ICON_PATH"].presence || "media/images/odoo_logo.svg"
33
+ }
34
+ end
35
+
36
+ config_accessor :authorizations do
37
+ [:odoo_member]
38
+ end
39
+
40
+ class Error < StandardError; end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+
5
+ module Decidim
6
+ module Odoo
7
+ module Generators
8
+ class InstallGenerator < Rails::Generators::Base
9
+ desc "This generator modifies secrets file adding odoo to omniauth methods"
10
+ def secrets
11
+ case Rails.env
12
+ when "development"
13
+ inject_into_file "development_app/config/secrets.yml", after: "icon: phone" do
14
+ <<~YAML
15
+ |
16
+ | odoo_keycloak:
17
+ | enabled: true
18
+ | icon_path: media/images/odoo_logo.svg
19
+ YAML
20
+ .gsub(/^ *\|/, "").rstrip
21
+ end
22
+ when "test"
23
+ inject_into_file "spec/decidim_dummy_app/config/secrets.yml", after: "app_secret: fake-facebook-app-secret" do
24
+ <<~YAML
25
+ |
26
+ | odoo_keycloak:
27
+ | enabled: false
28
+ | icon_path: media/images/odoo_logo.svg
29
+ YAML
30
+ .gsub(/^ *\|/, "").rstrip
31
+ end
32
+ end
33
+ end
34
+
35
+ desc "This generator copies the initializer file"
36
+ def initializers
37
+ Dir.chdir(Rails.env.test? ? "spec/decidim_dummy_app" : "development_app") do
38
+ FileUtils.cp(
39
+ "#{__dir__}/templates/#{Rails.env}_odoo_config.rb",
40
+ "config/initializers/odoo_config.rb"
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ Decidim::Odoo.configure do |config|
4
+ # Configure api credentials
5
+ config.api = {
6
+ base_url: ENV["ODOO_API_BASE_URL"].presence,
7
+ api_key: ENV["ODOO_API_API_KEY"].presence
8
+ }
9
+
10
+ # Configure omniauth secrets
11
+ config.keycloak_omniauth = {
12
+ enabled: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_ID"].present?,
13
+ client_id: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_ID"].presence,
14
+ client_secret: ENV["OMNIAUTH_ODOO_KEYCLOAK_CLIENT_SECRET"].presence,
15
+ client_options: {
16
+ site: ENV["OMNIAUTH_ODOO_KEYCLOAK_SITE"].presence,
17
+ realm: ENV["OMNIAUTH_ODOO_KEYCLOAK_REALM"].presence
18
+ },
19
+ icon_path: ENV["OMNIAUTH_ODOO_KEYCLOAK_ICON_PATH"].presence || "media/images/odoo_logo.svg"
20
+ }
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ Decidim::Odoo.configure do |config|
4
+ # Configure api credentials
5
+ config.api = {
6
+ base_url: "https://test.odoo.api.example.org",
7
+ api_key: "test-api-key"
8
+ }
9
+
10
+ # Configure omniauth secrets
11
+ config.keycloak_omniauth = {
12
+ enabled: true,
13
+ client_id: "test-client-id",
14
+ client_secret: "test-client-secret",
15
+ client_options: {
16
+ site: "https://test.odoo.oauth.example.org",
17
+ realm: "test-realm"
18
+ }
19
+ }
20
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "omniauth-keycloak"
4
+
5
+ module OmniAuth
6
+ module Strategies
7
+ class OdooKeycloak < OmniAuth::Strategies::KeycloakOpenId
8
+ option :name, "odoo_keycloak"
9
+
10
+ uid { odoo_info[:ref] }
11
+
12
+ info do
13
+ {
14
+ nickname: odoo_info[:vat],
15
+ name: odoo_info[:name],
16
+ email: odoo_info[:email]
17
+ }
18
+ end
19
+
20
+ def odoo_info
21
+ @odoo_info ||= ::Decidim::Odoo::Api::FindPartnerByVat.new(raw_info["preferred_username"]).result
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :decidim do
4
+ namespace :odoo do
5
+ # invoke with 'bundle exec rake "civicrm:sync:groups"'
6
+
7
+ namespace :sync do
8
+ desc "Sync members with Odoo API"
9
+ task members: :environment do
10
+ Decidim::Organization.find_each do |organization|
11
+ Decidim::Odoo::SyncUsersJob.perform_later(organization.id)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: decidim-odoo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Francisco Bolívar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-07-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: decidim-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.25.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '0.27'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.25.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.27'
33
+ - !ruby/object:Gem::Dependency
34
+ name: omniauth-keycloak
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: decidim-dev
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.25.0
54
+ - - "<"
55
+ - !ruby/object:Gem::Version
56
+ version: '0.27'
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.25.0
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.27'
67
+ description: A Decidim module to sync Odoo users who connect to the platform using
68
+ Keycloak OpenID OAuth.
69
+ email:
70
+ - francisco.bolivar@nazaries.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - LICENSE-AGPLv3.txt
76
+ - README.md
77
+ - Rakefile
78
+ - app/commands/decidim/odoo/sync_user.rb
79
+ - app/controllers/concerns/decidim/odoo/admin/members/filterable.rb
80
+ - app/controllers/decidim/odoo/admin/members_controller.rb
81
+ - app/forms/decidim/odoo/verifications/odoo_member.rb
82
+ - app/helpers/decidim/odoo/admin/odoo_helper.rb
83
+ - app/jobs/decidim/odoo/auto_verification_job.rb
84
+ - app/jobs/decidim/odoo/omniauth_user_sync_job.rb
85
+ - app/jobs/decidim/odoo/sync_users_job.rb
86
+ - app/models/concerns/decidim/odoo/user_override.rb
87
+ - app/models/decidim/odoo/user.rb
88
+ - app/packs/entrypoints/decidim_odoo.js
89
+ - app/packs/images/odoo_logo.svg
90
+ - app/views/decidim/odoo/admin/members/index.html.erb
91
+ - config/assets.rb
92
+ - config/i18n-tasks.yml
93
+ - config/locales/en.yml
94
+ - db/migrate/20230713143501_create_decidim_odoo_users.rb
95
+ - lib/decidim/odoo.rb
96
+ - lib/decidim/odoo/admin.rb
97
+ - lib/decidim/odoo/admin_engine.rb
98
+ - lib/decidim/odoo/api.rb
99
+ - lib/decidim/odoo/api/base/base_query.rb
100
+ - lib/decidim/odoo/api/base/request.rb
101
+ - lib/decidim/odoo/api/find_partner.rb
102
+ - lib/decidim/odoo/api/find_partner_by_vat.rb
103
+ - lib/decidim/odoo/engine.rb
104
+ - lib/decidim/odoo/test/factories.rb
105
+ - lib/decidim/odoo/test/shared_contexts.rb
106
+ - lib/decidim/odoo/version.rb
107
+ - lib/generators/decidim/odoo/install_generator.rb
108
+ - lib/generators/decidim/odoo/templates/development_odoo_config.rb
109
+ - lib/generators/decidim/odoo/templates/test_odoo_config.rb
110
+ - lib/omniauth/strategies/odoo_keycloak.rb
111
+ - lib/tasks/decidim_odoo.rake
112
+ homepage: https://github.com/decidim/decidim-module-odoo
113
+ licenses:
114
+ - AGPL-3.0
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '2.7'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubygems_version: 3.2.22
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: A decidim odoo module
135
+ test_files: []