flex_commerce_api 0.6.57

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 (170) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +6 -0
  3. data/.gitignore +14 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +1065 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +3 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +56 -0
  12. data/Rakefile +1 -0
  13. data/app/models/address.rb +41 -0
  14. data/app/models/asset_file.rb +26 -0
  15. data/app/models/asset_folder.rb +14 -0
  16. data/app/models/bundle.rb +20 -0
  17. data/app/models/bundle_group.rb +15 -0
  18. data/app/models/cart.rb +136 -0
  19. data/app/models/category.rb +70 -0
  20. data/app/models/category_tree.rb +11 -0
  21. data/app/models/component.rb +8 -0
  22. data/app/models/container_coupon.rb +12 -0
  23. data/app/models/country.rb +11 -0
  24. data/app/models/coupon.rb +18 -0
  25. data/app/models/customer_account.rb +96 -0
  26. data/app/models/customer_account_authentication.rb +5 -0
  27. data/app/models/customer_segment.rb +6 -0
  28. data/app/models/customer_segment_member.rb +6 -0
  29. data/app/models/data_attribute.rb +6 -0
  30. data/app/models/data_store_record.rb +9 -0
  31. data/app/models/data_store_type.rb +9 -0
  32. data/app/models/discount_summary.rb +12 -0
  33. data/app/models/email.rb +5 -0
  34. data/app/models/ewis_opt_in.rb +8 -0
  35. data/app/models/external_url.rb +6 -0
  36. data/app/models/free_shipping_promotion.rb +12 -0
  37. data/app/models/import.rb +6 -0
  38. data/app/models/import_entry.rb +6 -0
  39. data/app/models/line_item.rb +34 -0
  40. data/app/models/line_item_discount.rb +7 -0
  41. data/app/models/markdown_price.rb +11 -0
  42. data/app/models/menu.rb +36 -0
  43. data/app/models/menu_item.rb +7 -0
  44. data/app/models/menu_item_item.rb +5 -0
  45. data/app/models/note.rb +18 -0
  46. data/app/models/order.rb +38 -0
  47. data/app/models/password_recovery.rb +20 -0
  48. data/app/models/payment_address_verification.rb +13 -0
  49. data/app/models/payment_process.rb +13 -0
  50. data/app/models/payment_provider.rb +15 -0
  51. data/app/models/payment_transaction.rb +13 -0
  52. data/app/models/product.rb +99 -0
  53. data/app/models/product_asset_file.rb +12 -0
  54. data/app/models/promotion.rb +19 -0
  55. data/app/models/promotion_qualifying_product_exclusion.rb +8 -0
  56. data/app/models/redirect.rb +14 -0
  57. data/app/models/refund.rb +14 -0
  58. data/app/models/remote_address.rb +22 -0
  59. data/app/models/remote_line_item.rb +11 -0
  60. data/app/models/remote_order.rb +15 -0
  61. data/app/models/remote_shipping_method.rb +12 -0
  62. data/app/models/report.rb +18 -0
  63. data/app/models/report_invocation.rb +18 -0
  64. data/app/models/retail_store.rb +18 -0
  65. data/app/models/role.rb +6 -0
  66. data/app/models/search_suggestion.rb +17 -0
  67. data/app/models/section.rb +9 -0
  68. data/app/models/session.rb +8 -0
  69. data/app/models/shipping_method.rb +26 -0
  70. data/app/models/slug.rb +19 -0
  71. data/app/models/static_page.rb +60 -0
  72. data/app/models/static_page_folder.rb +8 -0
  73. data/app/models/stock_level.rb +21 -0
  74. data/app/models/tax_code.rb +6 -0
  75. data/app/models/taxonomy.rb +5 -0
  76. data/app/models/template.rb +9 -0
  77. data/app/models/template_component.rb +11 -0
  78. data/app/models/template_definition.rb +12 -0
  79. data/app/models/template_section.rb +12 -0
  80. data/app/models/user.rb +8 -0
  81. data/app/models/user_profile.rb +6 -0
  82. data/app/models/v2/create_order.rb +10 -0
  83. data/app/models/v2/deallocate_order.rb +10 -0
  84. data/app/models/v2/line_item.rb +9 -0
  85. data/app/models/v2/order.rb +9 -0
  86. data/app/models/v2/unallocate_order.rb +10 -0
  87. data/app/models/variant.rb +18 -0
  88. data/app/models/webhook.rb +17 -0
  89. data/app/services/param_to_shql.rb +72 -0
  90. data/app/services/surrogate_keys.rb +44 -0
  91. data/bin/console +14 -0
  92. data/bin/setup +7 -0
  93. data/config/locales/payments.en.yml +3 -0
  94. data/flex-commerce-api.gemspec +41 -0
  95. data/lib/flex_commerce.rb +95 -0
  96. data/lib/flex_commerce_api.rb +21 -0
  97. data/lib/flex_commerce_api/api_base.rb +11 -0
  98. data/lib/flex_commerce_api/base_resource.rb +250 -0
  99. data/lib/flex_commerce_api/config.rb +55 -0
  100. data/lib/flex_commerce_api/error/access_denied.rb +6 -0
  101. data/lib/flex_commerce_api/error/bad_request.rb +10 -0
  102. data/lib/flex_commerce_api/error/base.rb +12 -0
  103. data/lib/flex_commerce_api/error/client_error.rb +7 -0
  104. data/lib/flex_commerce_api/error/connection_error.rb +6 -0
  105. data/lib/flex_commerce_api/error/internal_server.rb +37 -0
  106. data/lib/flex_commerce_api/error/not_found.rb +13 -0
  107. data/lib/flex_commerce_api/error/record_invalid.rb +16 -0
  108. data/lib/flex_commerce_api/error/unexpected_status.rb +7 -0
  109. data/lib/flex_commerce_api/errors.rb +13 -0
  110. data/lib/flex_commerce_api/json_api_client_extension/builder.rb +28 -0
  111. data/lib/flex_commerce_api/json_api_client_extension/capture_surrogate_keys_middleware.rb +16 -0
  112. data/lib/flex_commerce_api/json_api_client_extension/flexible_connection.rb +59 -0
  113. data/lib/flex_commerce_api/json_api_client_extension/has_many_association_proxy.rb +60 -0
  114. data/lib/flex_commerce_api/json_api_client_extension/included_data.rb +27 -0
  115. data/lib/flex_commerce_api/json_api_client_extension/json_format_middleware.rb +20 -0
  116. data/lib/flex_commerce_api/json_api_client_extension/logging_middleware.rb +24 -0
  117. data/lib/flex_commerce_api/json_api_client_extension/paginator.rb +26 -0
  118. data/lib/flex_commerce_api/json_api_client_extension/parse_json.rb +23 -0
  119. data/lib/flex_commerce_api/json_api_client_extension/parsers/parser.rb +16 -0
  120. data/lib/flex_commerce_api/json_api_client_extension/previewed_request_middleware.rb +17 -0
  121. data/lib/flex_commerce_api/json_api_client_extension/remote_builder.rb +29 -0
  122. data/lib/flex_commerce_api/json_api_client_extension/requestor.rb +42 -0
  123. data/lib/flex_commerce_api/json_api_client_extension/save_request_body_middleware.rb +20 -0
  124. data/lib/flex_commerce_api/json_api_client_extension/status_middleware.rb +40 -0
  125. data/lib/flex_commerce_api/v2/api_base.rb +13 -0
  126. data/lib/flex_commerce_api/version.rb +3 -0
  127. data/lib/json_erb.rb +9 -0
  128. data/lib/json_struct.rb +73 -0
  129. data/lib/patches.rb +4 -0
  130. data/lib/patches/json_api_client/resource.rb +50 -0
  131. data/lib/paypal_express.rb +3 -0
  132. data/lib/paypal_express/additional_info.rb +45 -0
  133. data/lib/paypal_express/api.rb +86 -0
  134. data/lib/paypal_express/auth.rb +83 -0
  135. data/lib/paypal_express/cart_shipping_method.rb +38 -0
  136. data/lib/paypal_express/exception/access_denied.rb +10 -0
  137. data/lib/paypal_express/exception/connection_error.rb +10 -0
  138. data/lib/paypal_express/exception/not_authorized.rb +10 -0
  139. data/lib/paypal_express/exception/transaction.rb +15 -0
  140. data/lib/paypal_express/generate_summary.rb +118 -0
  141. data/lib/paypal_express/process/paypal_params.rb +123 -0
  142. data/lib/paypal_express/process/response_parser.rb +146 -0
  143. data/lib/paypal_express/setup.rb +94 -0
  144. data/lib/paypal_express/shipping_methods_for_cart.rb +46 -0
  145. data/lib/retry.rb +20 -0
  146. data/schemas/jsonapi/schema.json +370 -0
  147. data/schemas/shift/v1/documents/collection/address.json +45 -0
  148. data/schemas/shift/v1/documents/collection/asset_file.json +43 -0
  149. data/schemas/shift/v1/documents/collection/asset_folder.json +43 -0
  150. data/schemas/shift/v1/documents/collection/customer_account.json +50 -0
  151. data/schemas/shift/v1/documents/collection/markdown_price.json +43 -0
  152. data/schemas/shift/v1/documents/collection/product.json +43 -0
  153. data/schemas/shift/v1/documents/collection/variant.json +43 -0
  154. data/schemas/shift/v1/documents/member/address.json +39 -0
  155. data/schemas/shift/v1/documents/member/asset_file.json +37 -0
  156. data/schemas/shift/v1/documents/member/asset_folder.json +39 -0
  157. data/schemas/shift/v1/documents/member/customer_account.json +44 -0
  158. data/schemas/shift/v1/documents/member/markdown_price.json +37 -0
  159. data/schemas/shift/v1/documents/member/product.json +39 -0
  160. data/schemas/shift/v1/documents/member/variant.json +46 -0
  161. data/schemas/shift/v1/resources/address.json +130 -0
  162. data/schemas/shift/v1/resources/asset_file.json +146 -0
  163. data/schemas/shift/v1/resources/asset_folder.json +188 -0
  164. data/schemas/shift/v1/resources/customer_account.json +339 -0
  165. data/schemas/shift/v1/resources/markdown_price.json +52 -0
  166. data/schemas/shift/v1/resources/product.json +230 -0
  167. data/schemas/shift/v1/resources/variant.json +298 -0
  168. data/tasks/json_schema.thor +275 -0
  169. data/todo.md +8 -0
  170. metadata +470 -0
@@ -0,0 +1,95 @@
1
+ module FlexCommerce
2
+ def self.gem_root
3
+ File.expand_path("../", __dir__)
4
+ end
5
+
6
+ # V2 Models
7
+ module V2
8
+ autoload :CreateOrder, File.join(FlexCommerce.gem_root, "app", "models", "v2", "create_order")
9
+ autoload :DeallocateOrder, File.join(FlexCommerce.gem_root, "app", "models", "v2", "deallocate_order")
10
+ autoload :LineItem, File.join(FlexCommerce.gem_root, "app", "models", "v2", "line_item")
11
+ autoload :Order, File.join(FlexCommerce.gem_root, "app", "models", "v2", "order")
12
+ autoload :UnallocateOrder, File.join(FlexCommerce.gem_root, "app", "models", "v2", "unallocate_order")
13
+ end
14
+
15
+ # V1 Models
16
+ autoload :Address, File.join(gem_root, "app", "models", "address")
17
+ autoload :AssetFile, File.join(gem_root, "app", "models", "asset_file")
18
+ autoload :AssetFolder, File.join(gem_root, "app", "models", "asset_folder")
19
+ autoload :Bundle, File.join(gem_root, "app", "models", "bundle")
20
+ autoload :BundleGroup, File.join(gem_root, "app", "models", "bundle_group")
21
+ autoload :Cart, File.join(gem_root, "app", "models", "cart")
22
+ autoload :Category, File.join(gem_root, "app", "models", "category")
23
+ autoload :CategoryTree, File.join(gem_root, "app", "models", "category_tree")
24
+ autoload :Component, File.join(gem_root, "app", "models", "component")
25
+ autoload :ContainerCoupon, File.join(gem_root, "app", "models", "container_coupon")
26
+ autoload :Country, File.join(gem_root, "app", "models", "country")
27
+ autoload :Coupon, File.join(gem_root, "app", "models", "coupon")
28
+ autoload :CustomerAccount, File.join(gem_root, "app", "models", "customer_account")
29
+ autoload :CustomerAccountAuthentication, File.join(gem_root, "app", "models", "customer_account_authentication")
30
+ autoload :CustomerSegment, File.join(gem_root, "app", "models", "customer_segment")
31
+ autoload :CustomerSegmentMember, File.join(gem_root, "app", "models", "customer_segment_member")
32
+ autoload :DataAttribute, File.join(gem_root, "app", "models", "data_attribute")
33
+ autoload :DataStoreRecord, File.join(gem_root, "app", "models", "data_store_record")
34
+ autoload :DataStoreType, File.join(gem_root, "app", "models", "data_store_type")
35
+ autoload :DiscountSummary, File.join(gem_root, "app", "models", "discount_summary")
36
+ autoload :Email, File.join(gem_root, "app", "models", "email")
37
+ autoload :EwisOptIn, File.join(gem_root, "app", "models", "ewis_opt_in")
38
+ autoload :ExternalUrl, File.join(gem_root, "app", "models", "external_url")
39
+ autoload :FreeShippingPromotion, File.join(gem_root, "app", "models", "free_shipping_promotion")
40
+ autoload :Import, File.join(gem_root, "app", "models", "import")
41
+ autoload :ImportEntry, File.join(gem_root, "app", "models", "import_entry")
42
+ autoload :LineItem, File.join(gem_root, "app", "models", "line_item")
43
+ autoload :LineItemDiscount, File.join(gem_root, "app", "models", "line_item_discount")
44
+ autoload :MarkdownPrice, File.join(gem_root, "app", "models", "markdown_price")
45
+ autoload :Menu, File.join(gem_root, "app", "models", "menu")
46
+ autoload :MenuItem, File.join(gem_root, "app", "models", "menu_item")
47
+ autoload :MenuItemItem, File.join(gem_root, "app", "models", "menu_item_item")
48
+ autoload :Note, File.join(gem_root, "app", "models", "note")
49
+ autoload :Order, File.join(gem_root, "app", "models", "order")
50
+ autoload :PasswordRecovery, File.join(gem_root, "app", "models", "password_recovery")
51
+ autoload :PaymentAdditionalInfo, File.join(gem_root, "app", "models", "payment_additional_info")
52
+ autoload :PaymentAddressVerification, File.join(gem_root, "app", "models", "payment_address_verification")
53
+ autoload :PaymentProcess, File.join(gem_root, "app", "models", "payment_process")
54
+ autoload :PaymentProvider, File.join(gem_root, "app", "models", "payment_provider")
55
+ autoload :PaymentProviderSetup, File.join(gem_root, "app", "models", "payment_provider_setup")
56
+ autoload :PaymentTransaction, File.join(gem_root, "app", "models", "payment_transaction")
57
+ autoload :Product, File.join(gem_root, "app", "models", "product")
58
+ autoload :ProductAssetFile, File.join(gem_root, "app", "models", "product_asset_file")
59
+ autoload :Promotion, File.join(gem_root, "app", "models", "promotion")
60
+ autoload :PromotionQualifyingProductExclusion, File.join(gem_root, "app", "models", "promotion_qualifying_product_exclusion")
61
+ autoload :Redirect, File.join(gem_root, "app", "models", "redirect")
62
+ autoload :Refund, File.join(gem_root, "app", "models", "refund")
63
+ autoload :RemoteAddress, File.join(gem_root, "app", "models", "remote_address")
64
+ autoload :RemoteLineItem, File.join(gem_root, "app", "models", "remote_line_item")
65
+ autoload :RemoteOrder, File.join(gem_root, "app", "models", "remote_order")
66
+ autoload :RemoteShippingMethod, File.join(gem_root, "app", "models", "remote_shipping_method")
67
+ autoload :Role, File.join(gem_root, "app", "models", "role")
68
+ autoload :Report, File.join(gem_root, "app", "models", "report")
69
+ autoload :ReportInvocation, File.join(gem_root, "app", "models", "report_invocation")
70
+ autoload :RetailStore, File.join(gem_root, "app", "models", "retail_store")
71
+ autoload :SearchSuggestion, File.join(gem_root, "app", "models", "search_suggestion")
72
+ autoload :Section, File.join(gem_root, "app", "models", "section")
73
+ autoload :Session, File.join(gem_root, "app", "models", "session")
74
+ autoload :ShippingMethod, File.join(gem_root, "app", "models", "shipping_method")
75
+ autoload :Slug, File.join(gem_root, "app", "models", "slug")
76
+ autoload :StaticPage, File.join(gem_root, "app", "models", "static_page")
77
+ autoload :StaticPageFolder, File.join(gem_root, "app", "models", "static_page_folder")
78
+ autoload :StockLevel, File.join(gem_root, "app", "models", "stock_level")
79
+ autoload :TaxCode, File.join(gem_root, "app", "models", "tax_code")
80
+ autoload :Taxonomy, File.join(gem_root, "app", "models", "taxonomy")
81
+ autoload :Template, File.join(gem_root, "app", "models", "template")
82
+ autoload :TemplateComponent, File.join(gem_root, "app", "models", "template_component")
83
+ autoload :TemplateDefinition, File.join(gem_root, "app", "models", "template_definition")
84
+ autoload :TemplateSection, File.join(gem_root, "app", "models", "template_section")
85
+ autoload :User, File.join(gem_root, "app", "models", "user")
86
+ autoload :UserProfile, File.join(gem_root, "app", "models", "user_profile")
87
+ autoload :Variant, File.join(gem_root, "app", "models", "variant")
88
+ autoload :Webhook, File.join(gem_root, "app", "models", "webhook")
89
+
90
+ # Services
91
+ autoload :ParamToShql, File.join(gem_root, "app", "services", "param_to_shql")
92
+ autoload :SurrogateKeys, File.join(gem_root, "app", "services", "surrogate_keys")
93
+ autoload :PaypalExpress, File.join(gem_root, "lib", "paypal_express")
94
+ autoload :Retry, File.join(gem_root, "lib", "retry")
95
+ end
@@ -0,0 +1,21 @@
1
+ require "patches"
2
+ require "paypal_express"
3
+ require "flex_commerce_api/config"
4
+ require "flex_commerce"
5
+ require "flex_commerce_api/errors"
6
+ require "flex_commerce_api/json_api_client_extension/parse_json"
7
+
8
+ module FlexCommerceApi
9
+ def self.config
10
+ FlexCommerceApi::Config.instance.tap do |config|
11
+ yield config if block_given?
12
+ config.reconfigure_all! if block_given?
13
+ end
14
+ end
15
+ def self.gem_root
16
+ File.expand_path("../", __dir__)
17
+ end
18
+ def self.logger
19
+ FlexCommerceApi::Config.instance.logger
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ require "flex_commerce_api/base_resource"
2
+
3
+ module FlexCommerceApi
4
+ class ApiBase < BaseResource
5
+ def self.endpoint_version
6
+ "v1"
7
+ end
8
+
9
+ reconfigure
10
+ end
11
+ end
@@ -0,0 +1,250 @@
1
+ require "json_api_client"
2
+ require "faraday/request/basic_authentication"
3
+ require "uri"
4
+ require "active_support/core_ext/hash/indifferent_access"
5
+ require "flex_commerce_api/json_api_client_extension/paginator"
6
+ require "flex_commerce_api/json_api_client_extension/requestor"
7
+ require "flex_commerce_api/json_api_client_extension/save_request_body_middleware"
8
+ require "flex_commerce_api/json_api_client_extension/logging_middleware"
9
+ require "flex_commerce_api/json_api_client_extension/status_middleware"
10
+ require "flex_commerce_api/json_api_client_extension/json_format_middleware"
11
+ require "flex_commerce_api/json_api_client_extension/previewed_request_middleware"
12
+ require "flex_commerce_api/json_api_client_extension/capture_surrogate_keys_middleware"
13
+ require "flex_commerce_api/json_api_client_extension/has_many_association_proxy"
14
+ require "flex_commerce_api/json_api_client_extension/builder"
15
+ require "flex_commerce_api/json_api_client_extension/flexible_connection"
16
+ require "flex_commerce_api/json_api_client_extension/parsers/parser"
17
+ require "flex_commerce_api/json_api_client_extension/remote_builder"
18
+
19
+ module FlexCommerceApi
20
+ #
21
+ # Base class for all flex commerce models
22
+ #
23
+ class BaseResource < JsonApiClient::Resource
24
+ PRIVATE_ATTRIBUTES = %w(id type relationships links meta)
25
+ RELATED_META_RESOURCES = %w(related-categories related-static_pages related-resources related-files related-products)
26
+
27
+ # set the api base url in an abstract base class
28
+ self.paginator = JsonApiClientExtension::Paginator
29
+ self.requestor_class = JsonApiClientExtension::Requestor
30
+ self.connection_class = ::FlexCommerceApi::JsonApiClientExtension::FlexibleConnection
31
+ self.parser = ::FlexCommerceApi::JsonApiClientExtension::Parsers::Parser
32
+
33
+ class << self
34
+ def create!(*args)
35
+ create(*args).tap do |resource|
36
+ raise(::FlexCommerceApi::Error::RecordInvalid.new(resource)) unless resource.errors.empty?
37
+ end
38
+ end
39
+
40
+ # @method all
41
+ # Returns all resources
42
+ # @return [FlexCommerceApi::ApiBase[]] An array of resources or an empty array
43
+
44
+ # @method paginate
45
+ # Paginates the list of resources by a preset page size
46
+ # @param [Hash] options The options to paginate with
47
+ # @param options [Numeric|String] :page The page to fetch
48
+
49
+ # @method find_all
50
+ # Finds many resources, always returning an array, even if 1 result
51
+ alias_method :find_all, :find
52
+
53
+ # @method find
54
+ # @param [String] spec The spec of what to find
55
+ #
56
+ # Finds a resource
57
+ # @return [FlexCommerceApi::ApiBase] resource The resource found
58
+ # @raise [FlexCommerceApi::Error::NotFound] If not found
59
+ def find(*args)
60
+ # This is required as currently the underlying gem returns an array
61
+ # even if 1 record is found. This is inconsistent with active record
62
+ result = super
63
+ result.length <= 1 ? result.first : result
64
+ end
65
+
66
+ # The username to use for authentication.
67
+ # @return [String] The username
68
+ def username
69
+ username = FlexCommerceApi.config.flex_account
70
+ username = URI.parse(site).path.split("/").reject(&:empty?).first if username.nil? || username.empty?
71
+ username
72
+ end
73
+
74
+ # The password to use for authentication. This is the same as
75
+ # the access key token from the flex platform.
76
+ # @return [String] The password
77
+ def password
78
+ FlexCommerceApi.config.flex_api_key
79
+ end
80
+
81
+ def path(params = nil, record = nil)
82
+ super(params)
83
+ end
84
+
85
+ def capture_surrogate_keys
86
+ Thread.current[:shift_surrogate_keys] = []
87
+ yield
88
+ Thread.current[:shift_surrogate_keys].uniq!
89
+ results = Thread.current[:shift_surrogate_keys].join(' ')
90
+ Thread.current[:shift_surrogate_keys] = nil
91
+ results
92
+ end
93
+
94
+ def reconfigure_all options = {}
95
+ self.subclasses.each do |sub|
96
+ sub.reconfigure_api_base options
97
+ end
98
+ end
99
+
100
+ def reconfigure_api_base options = {}
101
+ self.subclasses.each do |sub|
102
+ sub.reconfigure options
103
+ end
104
+ reconfigure options
105
+ end
106
+
107
+ def reconfigure options = {}
108
+ self.site = append_version(FlexCommerceApi.config.api_base_url)
109
+ base_options = {
110
+ adapter: FlexCommerceApi.config.adapter || :net_http,
111
+ http_cache: FlexCommerceApi.config.http_cache,
112
+ timeout: FlexCommerceApi.config.timeout,
113
+ open_timeout: FlexCommerceApi.config.open_timeout
114
+ }
115
+ self.connection_options.delete(:include_previewed)
116
+ self.connection_options = connection_options.merge(base_options).merge(options)
117
+ reload_connection_if_required
118
+ end
119
+
120
+ def reload_connection_if_required
121
+ _build_connection(true) if connection_object
122
+ end
123
+
124
+ # Allows ApiBase to be used as the class and the real class is then calculated from the type
125
+ def load(params)
126
+ return super unless self == FlexCommerceApi::ApiBase
127
+ klass = JsonApiClient::Utils.compute_type(FlexCommerce, params["type"].singularize.classify)
128
+ klass.load(params)
129
+ end
130
+
131
+ def append_version(base_url)
132
+ "#{base_url}/#{endpoint_version}"
133
+ end
134
+
135
+ def endpoint_version
136
+ raise NotImplementedError
137
+ end
138
+ end
139
+
140
+ def freeze
141
+ attributes.freeze
142
+ associations.freeze
143
+ links.freeze
144
+ relationships.freeze
145
+ self
146
+ end
147
+
148
+ # Ensures all attributes are with indifferent access
149
+ def initialize(attrs = {})
150
+ super attrs.with_indifferent_access
151
+ end
152
+
153
+ def save!
154
+ return if save
155
+ raise_record_invalid
156
+ end
157
+
158
+ def public_attributes
159
+ attributes.reject { |k, v| PRIVATE_ATTRIBUTES.include?(k.to_s) }
160
+ end
161
+
162
+ def meta_attribute(key)
163
+ begin
164
+ return self.send(key) if RELATED_META_RESOURCES.include?(attributes[:meta_attributes][key][:data_type])
165
+ attributes[:meta_attributes][key][:value]
166
+ rescue NoMethodError
167
+ nil
168
+ end
169
+ end
170
+
171
+ def method_missing(method, *args)
172
+ if relationships and relationships.has_attribute?(method)
173
+ super
174
+ else
175
+ has_attribute?(method) || method.to_s=~(/=$/) || method.to_s=~/!$/ ? super : nil
176
+ end
177
+ end
178
+
179
+ def as_json_api(*args)
180
+ convert_relationship_attributes! super(*args)
181
+ end
182
+
183
+ private
184
+
185
+ def convert_relationship_attributes!(h)
186
+ valid_relationships = relationship_attributes
187
+ (h["attributes"].keys & valid_relationships).each do |attr|
188
+ h["attributes"][attr] = convert_relationship_attribute(h["attributes"][attr])
189
+ end
190
+ h
191
+ end
192
+
193
+ def relationship_attributes
194
+ @relationship_attributes ||= self.class.associations.map { |a| a.is_a?(JsonApiClient::Associations::HasMany::Association) ? "#{a.attr_name}_resources" : "#{a.attr_name}_resource" }
195
+ end
196
+
197
+ def convert_relationship_attribute(data)
198
+ case data
199
+ when Array
200
+ data.map do |d|
201
+ convert_relationship_attribute(d)
202
+ end
203
+ when FlexCommerceApi::ApiBase
204
+ data.as_json_api
205
+ else
206
+ data
207
+ end
208
+ end
209
+
210
+ def raise_record_invalid
211
+ raise(::FlexCommerceApi::Error::RecordInvalid.new(self))
212
+ end
213
+
214
+ # This is temporary code - eventually this will be in the lower level gem
215
+ def has_many_association_proxy(assoc_name, real_instance, options = {})
216
+ JsonApiClientExtension::HasManyAssociationProxy.new(real_instance, self, assoc_name, options)
217
+ end
218
+
219
+ # Gets a relationship using its related link - but returns a builder allowing for it to be
220
+ # paginated, searched and more.
221
+ def get_related(relationship)
222
+ relationship_definitions = relationships[relationship]
223
+ association = association_for(relationship)
224
+ raise "#{relationship} is not defined in #{self.class.name}" unless association
225
+ if relationship_definitions["links"] && url = relationship_definitions["links"]["related"]
226
+ url = URI.parse(url)
227
+ site = url.clone.tap { |u|
228
+ u.path = ""
229
+ u.query = nil
230
+ u.fragment = nil
231
+ }.to_s
232
+ path = url.clone.tap { |u|
233
+ u.scheme = nil
234
+ u.host = nil
235
+ u.port = nil
236
+ u.userinfo = nil
237
+ }.to_s
238
+ connection = if site.empty?
239
+ self.class.connection
240
+ else
241
+ FlexCommerceApi::JsonApiClientExtension::FlexibleConnection.new(self.class.connection_options.merge(site: site, add_json_api_extension: false, authenticate: false))
242
+ end
243
+ FlexCommerceApi::JsonApiClientExtension::RemoteBuilder.new(association.association_class, path: path, connection: connection)
244
+ end
245
+
246
+ end
247
+
248
+
249
+ end
250
+ end
@@ -0,0 +1,55 @@
1
+ require "singleton"
2
+ module FlexCommerceApi
3
+ #
4
+ # Global configuration object
5
+ #
6
+ # This is not accessed directly but using code similar to this example :-
7
+ #
8
+ # FlexCommerceApi.config do |config|
9
+ # config.flex_root_url=ENV["FLEX_ROOT_URL"]
10
+ # config.flex_account=ENV["FLEX_ACCOUNT"]
11
+ # config.flex_api_key=ENV["FLEX_API_KEY"]
12
+ # config.logger = Rails.logger
13
+ # config.order_test_mode = ENV.key?("ORDER_TEST_MODE")
14
+ # end
15
+ #
16
+ # The above code would typically be found in a rails initializer as an example.
17
+ class Config
18
+ include Singleton
19
+ # @!attribute flex_root_url
20
+ # The root url for the flex server. Must NOT include the account name at the end
21
+ # For example https://api.flexcommerce.com
22
+ # @!attribute flex_account
23
+ # The account to be used on the flex server.
24
+ # For example myaccount
25
+ # @!attribute flex_api_key
26
+ # The API key to access the flex server with. This comes from the 'Access Keys'
27
+ # section of the admin panel
28
+ # @!attribute order_test_mode
29
+ # The order test mode.This config determines if orders are processed as test or real orders
30
+ attr_accessor :flex_root_url, :flex_api_key, :flex_account, :logger, :adapter, :order_test_mode, :http_cache, :open_timeout, :timeout, :paypal_login, :paypal_password, :paypal_signature, :order_test_mode, :paypal_connection_errors_no_of_retries
31
+ attr_reader :api_version
32
+
33
+ def initialize
34
+ self.order_test_mode = false
35
+ self.http_cache = {}
36
+ self.open_timeout = ENV.fetch('SHIFT_OPEN_TIMEOUT', 2).to_i
37
+ self.timeout = ENV.fetch('SHIFT_TIMEOUT', 15).to_i
38
+ end
39
+
40
+ # The api base URL
41
+ # @return [String] The base URL for the flex system. Calculated from the
42
+ # flex_root_url and _api_verision
43
+ def api_base_url
44
+ "#{flex_root_url}/#{flex_account}"
45
+ end
46
+
47
+ # Informs all models that the configuration may have changed
48
+ # but only if ApiBase is defined - else nothing has loaded yet
49
+ # so they wont need reconfiguring
50
+ def reconfigure_all!
51
+ FlexCommerceApi::BaseResource.reconfigure_all if FlexCommerceApi.const_defined? "ApiBase"
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,6 @@
1
+ module FlexCommerceApi
2
+ module Error
3
+ class AccessDenied < ClientError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module FlexCommerceApi
2
+ module Error
3
+ class BadRequest < ClientError
4
+ def message
5
+ msg = response_env[:body]["errors"].map {|e| "#{e['title']} - #{e['detail']}"}.join(" , ")
6
+ "Bad Request #{msg}"
7
+ end
8
+ end
9
+ end
10
+ end