workarea-global_e 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintrc.json +37 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/workflows/ci.yml +77 -0
  7. data/.gitignore +20 -0
  8. data/.rubocop.yml +2 -0
  9. data/.ruby-version +1 -0
  10. data/CHANGELOG.md +261 -0
  11. data/Gemfile +16 -0
  12. data/README.md +39 -0
  13. data/Rakefile +59 -0
  14. data/app/assets/javascripts/workarea/storefront/global_e/modules/checkout_info_validator.js +122 -0
  15. data/app/assets/javascripts/workarea/storefront/global_e/modules/suppress_price_ranges.js +19 -0
  16. data/app/controllers/workarea/admin/country_exceptions_controller.rb +67 -0
  17. data/app/controllers/workarea/admin/fixed_prices_controller.rb +89 -0
  18. data/app/controllers/workarea/admin/orders_controller.decorator +6 -0
  19. data/app/controllers/workarea/storefront/application_controller.decorator +30 -0
  20. data/app/controllers/workarea/storefront/checkouts_controller.decorator +22 -0
  21. data/app/controllers/workarea/storefront/ge_checkouts_controller.rb +10 -0
  22. data/app/controllers/workarea/storefront/global_e_controller.rb +42 -0
  23. data/app/controllers/workarea/storefront/globale/api_controller.rb +108 -0
  24. data/app/controllers/workarea/storefront/globale/refund_controller.rb +65 -0
  25. data/app/controllers/workarea/storefront/users/logins_controller.decorator +13 -0
  26. data/app/helpers/workarea/admin/global_e_helpers.rb +28 -0
  27. data/app/models/workarea/address.decorator +11 -0
  28. data/app/models/workarea/catalog/product.decorator +14 -0
  29. data/app/models/workarea/fulfillment/status/partially_refunded.rb +13 -0
  30. data/app/models/workarea/fulfillment/status/refunded.rb +15 -0
  31. data/app/models/workarea/fulfillment.decorator +55 -0
  32. data/app/models/workarea/global_e/country_exception.rb +37 -0
  33. data/app/models/workarea/global_e/fixed_price.rb +93 -0
  34. data/app/models/workarea/global_e/order_api_events.rb +29 -0
  35. data/app/models/workarea/order/item.decorator +46 -0
  36. data/app/models/workarea/order/status/pending_global_e_fraud_check.rb +12 -0
  37. data/app/models/workarea/order.decorator +64 -0
  38. data/app/models/workarea/payment/status/global_e_appoved.rb +9 -0
  39. data/app/models/workarea/payment/status/pending_global_e_fraud_check.rb +9 -0
  40. data/app/models/workarea/payment/tender/global_e_payment.rb +16 -0
  41. data/app/models/workarea/payment.decorator +10 -0
  42. data/app/models/workarea/price_adjustment.decorator +13 -0
  43. data/app/models/workarea/price_adjustment_set.decorator +25 -0
  44. data/app/models/workarea/pricing/calculators/item_calculator.decorator +48 -0
  45. data/app/models/workarea/pricing/collection.decorator +90 -0
  46. data/app/models/workarea/pricing/discount/appliation_group.decorator +16 -0
  47. data/app/models/workarea/pricing/discount/international_item_proxy.rb +27 -0
  48. data/app/models/workarea/pricing/discount/international_order.rb +29 -0
  49. data/app/models/workarea/pricing/discount.decorator +65 -0
  50. data/app/models/workarea/pricing/price_distributor.decorator +37 -0
  51. data/app/models/workarea/pricing/request.decorator +17 -0
  52. data/app/models/workarea/pricing/sku.decorator +17 -0
  53. data/app/models/workarea/search/admin/order.decorator +11 -0
  54. data/app/models/workarea/shipping/sku.decorator +23 -0
  55. data/app/models/workarea/shipping.decorator +11 -0
  56. data/app/models/workarea/user.decorator +10 -0
  57. data/app/seeds/workarea/global_e_seeds.rb +66 -0
  58. data/app/services/workarea/create_fulfillment.decorator +12 -0
  59. data/app/services/workarea/global_e/address_details.rb +218 -0
  60. data/app/services/workarea/global_e/api/notify_order_refunded.rb +45 -0
  61. data/app/services/workarea/global_e/api/perform_order_payment.rb +46 -0
  62. data/app/services/workarea/global_e/api/remove_restricted_products.rb +28 -0
  63. data/app/services/workarea/global_e/api/send_order_to_merchant/item_pricer.rb +147 -0
  64. data/app/services/workarea/global_e/api/send_order_to_merchant/save_user.rb +59 -0
  65. data/app/services/workarea/global_e/api/send_order_to_merchant.rb +359 -0
  66. data/app/services/workarea/global_e/api/update_order_shipping_info.rb +38 -0
  67. data/app/services/workarea/global_e/api/update_order_status/canceled.rb +42 -0
  68. data/app/services/workarea/global_e/api/update_order_status.rb +28 -0
  69. data/app/services/workarea/global_e/attribute.rb +44 -0
  70. data/app/services/workarea/global_e/brand.rb +19 -0
  71. data/app/services/workarea/global_e/cart_user_details.rb +34 -0
  72. data/app/services/workarea/global_e/category.rb +19 -0
  73. data/app/services/workarea/global_e/checkout_cart_info.rb +358 -0
  74. data/app/services/workarea/global_e/custom_product_attribute.rb +19 -0
  75. data/app/services/workarea/global_e/discount.rb +215 -0
  76. data/app/services/workarea/global_e/merchant/brand.rb +21 -0
  77. data/app/services/workarea/global_e/merchant/category.rb +21 -0
  78. data/app/services/workarea/global_e/merchant/customer.rb +36 -0
  79. data/app/services/workarea/global_e/merchant/customer_details.rb +201 -0
  80. data/app/services/workarea/global_e/merchant/discount.rb +127 -0
  81. data/app/services/workarea/global_e/merchant/international_details.rb +296 -0
  82. data/app/services/workarea/global_e/merchant/order.rb +425 -0
  83. data/app/services/workarea/global_e/merchant/order_refund.rb +103 -0
  84. data/app/services/workarea/global_e/merchant/original_order.rb +28 -0
  85. data/app/services/workarea/global_e/merchant/parcel_tracking.rb +31 -0
  86. data/app/services/workarea/global_e/merchant/payment_details.rb +161 -0
  87. data/app/services/workarea/global_e/merchant/product.rb +222 -0
  88. data/app/services/workarea/global_e/merchant/refund_product.rb +69 -0
  89. data/app/services/workarea/global_e/merchant/response_info.rb +115 -0
  90. data/app/services/workarea/global_e/merchant_cart_product_attribute.rb +21 -0
  91. data/app/services/workarea/global_e/order_status.rb +20 -0
  92. data/app/services/workarea/global_e/order_status_details.rb +79 -0
  93. data/app/services/workarea/global_e/order_status_reason.rb +20 -0
  94. data/app/services/workarea/global_e/parcel.rb +53 -0
  95. data/app/services/workarea/global_e/product.rb +612 -0
  96. data/app/services/workarea/global_e/product_meta_data.rb +13 -0
  97. data/app/services/workarea/global_e/tracking_details.rb +23 -0
  98. data/app/services/workarea/global_e/update_order_dispatch_exception.rb +46 -0
  99. data/app/services/workarea/global_e/update_order_dispatch_request.rb +108 -0
  100. data/app/services/workarea/global_e/user_id_number_type.rb +21 -0
  101. data/app/services/workarea/global_e/users_details.rb +151 -0
  102. data/app/services/workarea/global_e/vat_category.rb +20 -0
  103. data/app/services/workarea/global_e/vat_rate_type.rb +27 -0
  104. data/app/services/workarea/save_order_analytics.decorator +18 -0
  105. data/app/view_models/workarea/admin/order_view_model.decorator +13 -0
  106. data/app/view_models/workarea/storefront/cart_view_model.decorator +7 -0
  107. data/app/view_models/workarea/storefront/order_item_view_model.decorator +16 -0
  108. data/app/view_models/workarea/storefront/order_view_model.decorator +45 -0
  109. data/app/view_models/workarea/storefront/product_view_model.decorator +35 -0
  110. data/app/views/workarea/admin/catalog_products/_country_exceptions_card.html.haml +31 -0
  111. data/app/views/workarea/admin/catalog_products/_global_e_attributes.html.haml +3 -0
  112. data/app/views/workarea/admin/catalog_products/_global_e_fields.html.haml +4 -0
  113. data/app/views/workarea/admin/country_exceptions/edit.html.haml +48 -0
  114. data/app/views/workarea/admin/country_exceptions/index.html.haml +47 -0
  115. data/app/views/workarea/admin/country_exceptions/new.html.haml +44 -0
  116. data/app/views/workarea/admin/fixed_prices/edit.html.haml +73 -0
  117. data/app/views/workarea/admin/fixed_prices/index.html.haml +55 -0
  118. data/app/views/workarea/admin/fixed_prices/new.html.haml +70 -0
  119. data/app/views/workarea/admin/orders/_global_e.html.haml +27 -0
  120. data/app/views/workarea/admin/orders/attributes.html.haml +131 -0
  121. data/app/views/workarea/admin/orders/global_e.html.haml +110 -0
  122. data/app/views/workarea/admin/orders/show.html.haml +27 -0
  123. data/app/views/workarea/admin/orders/tenders/_global_e_payment.html.haml +3 -0
  124. data/app/views/workarea/admin/pricing_skus/_cards.html.haml +98 -0
  125. data/app/views/workarea/storefront/cart_items/create.html.haml +71 -0
  126. data/app/views/workarea/storefront/carts/_pricing.html.haml +14 -0
  127. data/app/views/workarea/storefront/carts/show.html.haml +187 -0
  128. data/app/views/workarea/storefront/ge_checkouts/show.html.haml +1 -0
  129. data/app/views/workarea/storefront/global_e/_country_picker.html.haml +1 -0
  130. data/app/views/workarea/storefront/global_e/_head.html.haml +10 -0
  131. data/app/views/workarea/storefront/orders/_summary.html.haml +275 -0
  132. data/app/views/workarea/storefront/orders/tenders/_global_e_payment.html.haml +3 -0
  133. data/app/views/workarea/storefront/products/_pricing.html.haml +49 -0
  134. data/app/views/workarea/storefront/products/_restricted_item_text.html.haml +1 -0
  135. data/app/views/workarea/storefront/users/orders/_summary.html.haml +22 -0
  136. data/app/workers/workarea/global_e/update_order_dispatch.rb +28 -0
  137. data/app/workers/workarea/save_user_order_details.decorator +9 -0
  138. data/bin/rails +25 -0
  139. data/config/initializers/appends.rb +46 -0
  140. data/config/initializers/seeds.rb +1 -0
  141. data/config/initializers/workarea.rb +64 -0
  142. data/config/locales/en.yml +105 -0
  143. data/config/routes.rb +31 -0
  144. data/lib/workarea/global_e/engine.rb +10 -0
  145. data/lib/workarea/global_e/error.rb +8 -0
  146. data/lib/workarea/global_e/version.rb +5 -0
  147. data/lib/workarea/global_e.rb +58 -0
  148. data/script/admin_ci +5 -0
  149. data/script/ci +8 -0
  150. data/script/core_ci +5 -0
  151. data/script/plugins_ci +5 -0
  152. data/script/storefront_ci +5 -0
  153. data/test/dummy/.ruby-version +1 -0
  154. data/test/dummy/Rakefile +6 -0
  155. data/test/dummy/app/assets/config/manifest.js +3 -0
  156. data/test/dummy/app/assets/images/.keep +0 -0
  157. data/test/dummy/app/assets/javascripts/application.js +14 -0
  158. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  159. data/test/dummy/app/controllers/application_controller.rb +2 -0
  160. data/test/dummy/app/controllers/concerns/.keep +0 -0
  161. data/test/dummy/app/helpers/application_helper.rb +2 -0
  162. data/test/dummy/app/jobs/application_job.rb +2 -0
  163. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  164. data/test/dummy/app/models/concerns/.keep +0 -0
  165. data/test/dummy/app/views/layouts/application.html.erb +15 -0
  166. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  167. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  168. data/test/dummy/bin/bundle +3 -0
  169. data/test/dummy/bin/rails +4 -0
  170. data/test/dummy/bin/rake +4 -0
  171. data/test/dummy/bin/setup +28 -0
  172. data/test/dummy/bin/update +28 -0
  173. data/test/dummy/bin/yarn +11 -0
  174. data/test/dummy/config/application.rb +23 -0
  175. data/test/dummy/config/boot.rb +5 -0
  176. data/test/dummy/config/environment.rb +5 -0
  177. data/test/dummy/config/environments/development.rb +52 -0
  178. data/test/dummy/config/environments/production.rb +83 -0
  179. data/test/dummy/config/environments/test.rb +45 -0
  180. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  181. data/test/dummy/config/initializers/assets.rb +14 -0
  182. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  183. data/test/dummy/config/initializers/content_security_policy.rb +25 -0
  184. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  185. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  186. data/test/dummy/config/initializers/inflections.rb +16 -0
  187. data/test/dummy/config/initializers/mime_types.rb +4 -0
  188. data/test/dummy/config/initializers/workarea.rb +5 -0
  189. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  190. data/test/dummy/config/locales/en.yml +33 -0
  191. data/test/dummy/config/puma.rb +34 -0
  192. data/test/dummy/config/routes.rb +5 -0
  193. data/test/dummy/config/secrets.yml +18 -0
  194. data/test/dummy/config/spring.rb +6 -0
  195. data/test/dummy/config.ru +5 -0
  196. data/test/dummy/db/seeds.rb +2 -0
  197. data/test/dummy/lib/assets/.keep +0 -0
  198. data/test/dummy/log/.keep +0 -0
  199. data/test/factories/workarea/global_e_factories.rb +836 -0
  200. data/test/integration/workarea/admin/catalog_product_country_exceptions_integration_test.rb +81 -0
  201. data/test/integration/workarea/admin/global_e_jump_to_integration_test.rb +20 -0
  202. data/test/integration/workarea/admin/pricing_sku_fixed_prices_integration_test.rb +83 -0
  203. data/test/integration/workarea/storefront/global_e_api/receive_order_integration_test.rb +278 -0
  204. data/test/integration/workarea/storefront/global_e_api/receive_order_refund_integration_test.rb +25 -0
  205. data/test/integration/workarea/storefront/global_e_api/receive_payment_integration_test.rb +34 -0
  206. data/test/integration/workarea/storefront/global_e_api/receive_shipping_info_integration_test.rb +29 -0
  207. data/test/integration/workarea/storefront/global_e_api/remove_restricted_products_integration_test.rb +27 -0
  208. data/test/integration/workarea/storefront/global_e_api/update_order_status_integration_test.rb +29 -0
  209. data/test/integration/workarea/storefront/global_e_checkout_cart_info/fixed_pricing_test.rb +438 -0
  210. data/test/integration/workarea/storefront/global_e_checkout_cart_info/gift_card_test.rb +63 -0
  211. data/test/integration/workarea/storefront/global_e_checkout_cart_info_integration_test.rb +660 -0
  212. data/test/integration/workarea/storefront/global_e_checkouts_integration_test.rb +71 -0
  213. data/test/integration/workarea/storefront/users/global_e_logins_integration_test.rb +20 -0
  214. data/test/models/workarea/catalog/product_global_e_test.rb +13 -0
  215. data/test/models/workarea/fixed_pricing_test.rb +117 -0
  216. data/test/models/workarea/global_e/country_exception_test.rb +36 -0
  217. data/test/models/workarea/payment_test.decorator +31 -0
  218. data/test/models/workarea/pricing/calculators/item_calculator_fixed_prices_test.rb +83 -0
  219. data/test/models/workarea/pricing/collection_fixed_prices_test.rb +83 -0
  220. data/test/models/workarea/pricing/price_distributor_test.decorator +21 -0
  221. data/test/models/workarea/pricing/sku_fixed_price_test.rb +133 -0
  222. data/test/support/workarea/global_e_support.rb +18 -0
  223. data/test/system/workarea/admin/global_e_system_test.rb +21 -0
  224. data/test/system/workarea/storefront/global_e_cart_system_test.rb +48 -0
  225. data/test/system/workarea/storefront/global_e_order_history_system_test.rb +43 -0
  226. data/test/teaspoon_env.rb +6 -0
  227. data/test/test_helper.rb +9 -0
  228. data/test/view_models/workarea/admin/global_e_order_view_model_test.rb +22 -0
  229. data/test/workers/workarea/global_e/update_order_dispatch_test.rb +64 -0
  230. data/test/workers/workarea/global_e_save_user_order_details_test.rb +41 -0
  231. data/workarea-global_e.gemspec +16 -0
  232. metadata +293 -0
@@ -0,0 +1,44 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class Attribute
4
+
5
+ def initialize(code: nil, name: nil, type_code: nil)
6
+ @code = code
7
+ @name = name
8
+ @type_code = type_code
9
+ end
10
+
11
+ def as_json(*_args)
12
+ {
13
+ AttributeCode: attribute_code,
14
+ Name: name,
15
+ AttributeTypeCode: attribute_type_code
16
+ }.compact
17
+ end
18
+
19
+ # Custom attribute code denoting a Merchant-specific attribute such
20
+ # as Size, Color, etc. (to be mapped on Global-e side)
21
+ #
22
+ # @return [String]
23
+ #
24
+ def attribute_code
25
+ @code
26
+ end
27
+
28
+ # Attribute name
29
+ #
30
+ # @return [String]
31
+ #
32
+ def name
33
+ @name
34
+ end
35
+
36
+ # Code used to identify the attribute type on the Merchant’s site such
37
+ # as “size” for Size, “color” for Color, etc.
38
+ # (to be mapped on Global-e side)
39
+ def attribute_type_code
40
+ @type_code
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class Brand
4
+ # Brand code on the Merchant’s site (to be mapped on Global-e side)
5
+ #
6
+ # @return [String]
7
+ #
8
+ def brand_code
9
+ end
10
+
11
+ # Brand name
12
+ #
13
+ # @return [String]
14
+ #
15
+ def name
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class CartUserDetails
4
+ attr_reader :user
5
+
6
+ def initialize(user)
7
+ @user = user
8
+ end
9
+
10
+ def as_json(*args)
11
+ {
12
+ UserId: user_id,
13
+ AddressDetails: address_details
14
+ }.compact
15
+ end
16
+
17
+ # Internal User identifier on the Merchant’s site.
18
+ #
19
+ # @return [String]
20
+ #
21
+ def user_id
22
+ user.id.to_s
23
+ end
24
+
25
+ # All available addresses taken from the registered customer address book
26
+ #
27
+ # @return [Array<Workarea::GlobalE::AddressDetails>]
28
+ #
29
+ def address_details
30
+ @address_details ||= user.addresses.map { |address| AddressDetails.new user, address }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class Category
4
+ # Category code on the Merchant’s site (to be mapped on Global-e side)
5
+ #
6
+ # @return [String]
7
+ #
8
+ def category_code
9
+ end
10
+
11
+ # Category name
12
+ #
13
+ # @return [String]
14
+ #
15
+ def name
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,358 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class CheckoutCartInfo
4
+ attr_reader :order
5
+
6
+ # @param [Workarea::Order] order
7
+ #
8
+ def initialize(order)
9
+ @order = order
10
+ end
11
+
12
+ def to_json
13
+ {
14
+ productsList: products_list,
15
+ clientIp: client_ip,
16
+ userDetails: user_details,
17
+ discountsList: discounts_list,
18
+ cartId: cart_id
19
+ }.compact.to_json
20
+ end
21
+
22
+ # List of Product objects (specified in request body)
23
+ #
24
+ # @return [Array<Workarea::GlobalE::Product>]
25
+ #
26
+ def products_list
27
+ @product_list ||= order.items.map { |i| GlobalE::Product.from_order_item i }
28
+ end
29
+
30
+ # End customer’s IP address
31
+ # optional
32
+ #
33
+ # @return [String]
34
+ #
35
+ def client_ip
36
+ order.ip_address
37
+ end
38
+
39
+ # 2-char ISO country code of the shipping country either pre-defined
40
+ # using geo-location or actively selected by the end customer. This may
41
+ # be different from shipping_details.country_code property denoting the
42
+ # registered user’s country defined below.
43
+ #
44
+ # optional
45
+ #
46
+ # @return [String]
47
+ #
48
+ def country_code
49
+ end
50
+
51
+ # Shipping details of a registered user (if available on the Merchant’s
52
+ # site). If user_details property mentioned below is specified then
53
+ # shipping_details will be ignored.
54
+ #
55
+ # If country_code argument defined above is not specified, the shipping
56
+ # country must be specified in `shipping_details.country_code property.
57
+ # If not specified neither in country_code argument nor in
58
+ # shipping_details.country_code property, client_iP argument defined
59
+ # above becomes mandatory and will be used to determine the end user’s
60
+ # shipping country by Global-e system.
61
+ #
62
+ def shipping_details
63
+ end
64
+
65
+ # Billing details of a registered user (if available on the Merchant’s
66
+ # site). If user_details property mentioned below is specified then
67
+ # billing_details will be ignored.
68
+ #
69
+ def billing_details
70
+ end
71
+
72
+ # All available details of the user including all relevant addresses.
73
+ # If userDetails is not specified then shippingDetails and
74
+ # billingDetails properties will be used instead. userDetails property
75
+ # can be used by merchants who support multiple shipping and / or
76
+ # multiple billing addresses in user’s account.
77
+ #
78
+ # @return [Workarea::GlobalE::CartUserDetails]
79
+ #
80
+ def user_details
81
+ return unless user.present?
82
+
83
+ @user_details ||= GlobalE::CartUserDetails.new(user)
84
+ end
85
+
86
+ # IncludeVAT value returned from CountryCoefficients method
87
+ # (optional for the merchants not supporting browsing integration)
88
+ #
89
+ # @return [Integer]
90
+ #
91
+ def include_vat
92
+ end
93
+
94
+ # List of JSON-serialized Discounts to be applied to the cart.
95
+ # Discounts of any type (“cart”, “shipping”, etc.) may be specified.
96
+ #
97
+ # @return [Array<Workarea::GlobalE::Discount>]
98
+ #
99
+ def discounts_list
100
+ item_discounts + order_discounts
101
+ end
102
+
103
+ # 3-char ISO currency code denoting the end customer’s currency. If not
104
+ # specified, the Merchant’s default currency will be assumed by default.
105
+ #
106
+ # @return [String]
107
+ #
108
+ def current_code
109
+ end
110
+
111
+ # 3-char ISO currency code denoting the original currency on the
112
+ # Merchant’s site (before applying country coefficient and FX
113
+ # conversion). If not specified, the Merchant’s default currency will
114
+ # be assumed by default.
115
+ #
116
+ # @return [String]
117
+ #
118
+ def original_currency_code
119
+ end
120
+
121
+ # ISO culture code. If specified, the textual properties will be
122
+ # returned in the requested culture’s language if available. Texts in
123
+ # English will be returned by default.
124
+ #
125
+ # @retun [String]
126
+ #
127
+ def culture_code
128
+ end
129
+
130
+ # List of JSON-serialized Shipping Options available for local shipping
131
+ # of the order from the Merchant to Global-e’s Local Hub previously
132
+ # returned by ActiveHubDetails method.
133
+ # If “globaleintegration_standard” shipping method has been created and
134
+ # enabled for Global-e on the Merchant’s site, Global-e will prefer this
135
+ # Shipping Option when posting the order back to the Merchant’s site
136
+ # (using SendOrderToMerchant API method). Therefore, all other shipping
137
+ # methods available for the local shipping may be omitted in
138
+ # shippingOptionsList.
139
+ # (optional in GetCheckoutCartInfo)
140
+ #
141
+ # @return [Array<Workarea::GlobalE::ShippingOption>]
142
+ #
143
+ def shipping_options_list
144
+ end
145
+
146
+ # Identifier of the Global-e’s Local Hub previously returned by
147
+ # ActiveHubDetails method. If not specified, the default Merchant’s
148
+ # Hub will be used instead.
149
+ #
150
+ # @return [Integer]
151
+ #
152
+ def hub_id
153
+ end
154
+
155
+ # Total number of loyalty points currently available in the end
156
+ # customer’s user account on the Merchant’s site.
157
+ #
158
+ # @return [Float]
159
+ #
160
+ def loyalty_points_total
161
+ end
162
+
163
+ # Number of loyalty points to be earned for this purchase by the end
164
+ # customer on the Merchant’s site.
165
+ #
166
+ # @return [Float]
167
+ #
168
+ def loyalty_points_earned
169
+ end
170
+
171
+ # Number of loyalty points to be spent for this purchase by the end
172
+ # customer on the Merchant’s site.
173
+ #
174
+ # @return [Float]
175
+ #
176
+ def loyalty_points_spent
177
+ end
178
+
179
+ # Loyalty code specified by the end customer (or read from the end
180
+ # customer’s account) on the Merchant’s site.
181
+ #
182
+ # @return [String]
183
+ #
184
+ def loyalty_code
185
+ end
186
+
187
+ # VAT Registration Number of the end customer’s business entity
188
+ # validated with the merchant.
189
+ #
190
+ # @return [String]
191
+ #
192
+ def vat_registration_number
193
+ end
194
+
195
+ # Indicates if the end customer must not be charged VAT. This is usually
196
+ # set to TRUE for registered users who have validated their business
197
+ # entity’s VAT Registration Number with the merchant and are therefore
198
+ # VAT exempted.
199
+ #
200
+ # @return [Boolean]
201
+ #
202
+ def do_not_charge_vat
203
+ end
204
+
205
+ # Indicates if the Merchant offers free international shipping to the
206
+ # end customer.
207
+ #
208
+ # @return [Boolean]
209
+ #
210
+ def is_free_shipping
211
+ end
212
+
213
+ # Merchant’s free shipping coupon code applied by the end customer.
214
+ #
215
+ # @return [String]
216
+ #
217
+ def free_shipping_coupon_code
218
+ end
219
+
220
+ # List of available payment installment amounts.
221
+ # Example: {2,4,6,8} – This indicates that we should allow installments
222
+ # in 2, 4, 6 or 8 installment options (to be selected by the customer)
223
+ #
224
+ # @return [String]
225
+ #
226
+ def payment_installments
227
+ end
228
+
229
+ # List of JSON-serialized KeyValuePairs that denote parameter values to
230
+ # be specified in the respective Merchant’s RESTFul API action URLs.
231
+ # For example to instruct Global-e to include “en-AU” locale in
232
+ # SendOrderToMerhant call for this cart, urlParameters should include
233
+ # the following KeyValuePair: [{"Key":"locale", "Value":"en-AU"}]. In
234
+ # this example “locale” parameter should be configured for
235
+ # SendOrderToMerhant URL for this merchant on Global-e side.
236
+ #
237
+ # @return [Array<Hash>]
238
+ #
239
+ def url_parameters
240
+ end
241
+
242
+ # Code used on the merchant’s side to identify the web store where the
243
+ # current cart is originating from. This code should be used in case of
244
+ # multi-store setup on the merchant’s site.
245
+ #
246
+ # @return [String]
247
+ #
248
+ def web_store_code
249
+ end
250
+
251
+ # Code used on the merchant’s side to identify the web store instance
252
+ # where the current cart is originating from. This code should be used
253
+ # in case of multi-store domains setup on the merchant’s site.
254
+ #
255
+ # @return [String]
256
+ #
257
+ def web_store_instance_code
258
+ end
259
+
260
+ # Holds information on the registered user for apply loyalty points
261
+ # in the checkout page.
262
+ #
263
+ # @return [Workarea::GlobalE::LoyaltyPoints]
264
+ #
265
+ def loyalty_points
266
+ end
267
+
268
+ # Hash optionally generated by the merchant, to be returned to the
269
+ # merchant with order API call. This hash may be used for additional
270
+ # cart and order validation purposes on the Merchant’s side
271
+ #
272
+ # @return [String]
273
+ #
274
+ def merchant_cart_hash
275
+ end
276
+
277
+ # Indicates if end customer’s consent to receive emails from merchants
278
+ # should be pre-selected in Global- e checkout.
279
+ #
280
+ # @return [Boolean]
281
+ #
282
+ def allow_mails_from_merchant
283
+ end
284
+
285
+ # String that represents merchant order id if it’s known already at the
286
+ # point when the user is still in the cart page on the merchant’s store.
287
+ #
288
+ # @return [String]
289
+ #
290
+ def cart_id
291
+ end
292
+
293
+ private
294
+
295
+ def user
296
+ return unless order.user_id.present?
297
+
298
+ @user ||= User.find order.user_id
299
+ end
300
+
301
+ def shippings
302
+ @shippings ||= Shipping.by_order(order.id).to_a
303
+ end
304
+
305
+ def discounts
306
+ @discounts ||= Pricing::Discount.find(order.discount_ids).to_a
307
+ end
308
+
309
+ def discount_item_price_adjustments
310
+ order.items.flat_map do |order_item|
311
+ if order.fixed_pricing?
312
+ order_item.international_price_adjustments
313
+ else
314
+ order_item.price_adjustments
315
+ end.discounts.adjusting("item")
316
+ end.compact
317
+ end
318
+
319
+ def discount_order_price_adjustments
320
+ if order.fixed_pricing?
321
+ order.international_price_adjustments
322
+ else
323
+ order.price_adjustments
324
+ end.discounts.adjusting("order").group_discounts_by_id
325
+ end
326
+
327
+ def item_discounts
328
+ discount_item_price_adjustments.map do |price_adjustment|
329
+ discount = discounts.detect { |d| d.id.to_s == price_adjustment.data["discount_id"] }
330
+
331
+ GlobalE::Discount.new discount, order: order, price_adjustment: price_adjustment
332
+ end
333
+ end
334
+
335
+ def order_discounts
336
+ discount_order_price_adjustments.map do |price_adjustment|
337
+ discount = discounts.detect { |d| d.id.to_s == price_adjustment.data["discount_id"] }
338
+
339
+ GlobalE::Discount.new discount, order: order, price_adjustment: price_adjustment
340
+ end
341
+ end
342
+
343
+ def order_skus
344
+ order.items.map(&:sku)
345
+ end
346
+
347
+ def pricing
348
+ @pricing ||= Pricing::Collection.new(order_skus)
349
+ end
350
+
351
+ def is_fixed_priced_order?
352
+ pricing.records.all? do |sku|
353
+ sku.fixed_price_for(currency_code: order.currency, country: order.shipping_country)
354
+ end
355
+ end
356
+ end
357
+ end
358
+ end
@@ -0,0 +1,19 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class CustomProductAttribute
4
+ # Custom product attribute name that is used for product personalization by the end customer (e.g. engraving)
5
+ #
6
+ # @return [String]
7
+ #
8
+ def attribute_key
9
+ end
10
+
11
+ # Custom product attribute value that is used for product personalization by the end customer (e.g. engraving).
12
+ #
13
+ # @return [String]
14
+ #
15
+ def attribute_value
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,215 @@
1
+ module Workarea
2
+ module GlobalE
3
+ class Discount
4
+ attr_reader :discount, :order, :price_adjustment
5
+
6
+ def initialize(discount, order:, price_adjustment:)
7
+ @discount = discount
8
+ @order = order
9
+ @price_adjustment = price_adjustment
10
+ end
11
+
12
+ def as_json(*_args)
13
+ {
14
+ OriginalDiscountValue: original_discount_value,
15
+ VATRate: vat_rate,
16
+ LocalVATRate: local_vat_rate,
17
+ DiscountValue: discount_value,
18
+ Name: name,
19
+ Description: description,
20
+ CouponCode: coupon_code,
21
+ ProductCartItemId: product_cart_item_id,
22
+ DiscountCode: discount_code,
23
+ LoyaltyVoucherCode: loyalty_voucher_code,
24
+ DiscountType: discount_type,
25
+ CalculationMode: calculation_mode
26
+ }.compact
27
+ end
28
+
29
+ # Discount value in original Merchant’s currency including the local VAT,
30
+ # before applying any price modifications. This property always denotes
31
+ # the discount value in the default Merchant’s country, regardless of
32
+ # UseCountryVAT for the end customer’s current country.
33
+ #
34
+ # @return [Float]
35
+ #
36
+ def original_discount_value
37
+ return 0 if order.fixed_pricing?
38
+
39
+ if free_gift? && pricing_sku.present?
40
+ pricing_sku.find_price(quantity: 1).regular.to_f
41
+ else
42
+ price_adjustment.amount.abs.to_f
43
+ end
44
+ end
45
+
46
+ # VAT rate applied to this discount
47
+ #
48
+ # @return [Float]
49
+ #
50
+ def vat_rate
51
+ end
52
+
53
+ # VAT rate that would be applied to this discount if the order was placed
54
+ # by the local customer. This value must be specified if UseCountryVAT
55
+ # for the current Country is TRUE and therefore VATRate property actually
56
+ # denotes the VAT for the target country.
57
+ #
58
+ # @return [Float]
59
+ #
60
+ def local_vat_rate
61
+ end
62
+
63
+ # Discount value as displayed to the customer, after applying country
64
+ # coefficient, FX conversion and IncludeVAT handling.
65
+ #
66
+ # @return [Float]
67
+ #
68
+ def discount_value
69
+ return 0 unless order.fixed_pricing?
70
+
71
+ if free_gift? && pricing_sku.present?
72
+ pricing_sku.find_price(quantity: 1).regular.to_f
73
+ else
74
+ price_adjustment.amount.abs.to_f
75
+ end
76
+ end
77
+
78
+ # Discount name
79
+ #
80
+ # @return [String]
81
+ #
82
+ def name
83
+ discount.name
84
+ end
85
+
86
+ # Discount textual description
87
+ #
88
+ # @return [String]
89
+ #
90
+ def description
91
+ "#{discount.class.name.demodulize.underscore.titleize} - #{name}"
92
+ end
93
+
94
+ # Merchant’s coupon code used for this discount (applicable to
95
+ # coupon-based discounts only)
96
+ #
97
+ # @return [String]
98
+ #
99
+ def coupon_code
100
+ (discount_promo_codes & order_promo_codes).first
101
+ end
102
+
103
+ # Identifier of the product cart item related to this discount on the
104
+ # Merchant’s site. This property may be optionally specified in SendCart
105
+ # method only, so that the same value could be posted back when creating
106
+ # the order on the Merchant’s site with SendOrderToMerchant method.
107
+ #
108
+ # @return [String]
109
+ #
110
+ def product_cart_item_id
111
+ if price_adjustment.price == "item"
112
+ price_adjustment&._parent&.id&.to_s
113
+ end
114
+ end
115
+
116
+ # Discount code used to identify the discount on the Merchant’s site.
117
+ # This property may be optionally specified in SendCart method only, so
118
+ # that the same value could be posted back when creating the order on
119
+ # the Merchant’s site with SendOrderToMerchant method.
120
+ #
121
+ # @return [String]
122
+ #
123
+ def discount_code
124
+ price_adjustment.global_e_discount_code
125
+ end
126
+
127
+ # Code used on the Merchant’s site to identify the Loyalty Voucher
128
+ # that this discount is based on
129
+ #
130
+ # @return [String]
131
+ #
132
+ def loyalty_voucher_code
133
+ end
134
+
135
+ # One of the following possible values of DiscountTypeOptions enumeration
136
+ # denoting a type of a discount:
137
+ #
138
+ # | DiscountType Option Value | Name | Description |
139
+ # | 1 | Cart Discount | Discount related to volume, amount, coupon or another promotion value. |
140
+ # | 2 | Shipping Discount | Discount aimed to sponsor international shipping. |
141
+ # | 3 | Loyalty points discount | Discount applied against the Merchant’s loyalty points to be spent for this purchase. |
142
+ # | 4 | Duties discount | Discount aimed to sponsor taxes & duties pre- paid by the end customer in Global-e checkout. |
143
+ # | 5 | Checkout Loyalty Points Discount | Discount applied against the Merchant’s loyalty points in Global-e checkout. |
144
+ # | 6 | Payment Charge | Discount aimed to sponsor “Cash on Delivery” fee. |
145
+ #
146
+ # @return [Integer]
147
+ #
148
+ def discount_type
149
+ if GlobalE.shipping_discount_types.include? discount.class.name
150
+ 2
151
+ else
152
+ 1
153
+ end
154
+ end
155
+
156
+ # One of the following possible values of CalculationModeOptions
157
+ # enumeration denoting the calculation mode of a discount to be
158
+ # implemented by GEM:
159
+ #
160
+ # | CalculationMode Option Value | Name | Description |
161
+ # | 1 (default) | Percentage discount | Discount value specified in OriginalDiscountValue should be used for calculating the discount’s
162
+ # DiscountValue as percentage of the full product’s price (specified in Product.OriginalSalePrice
163
+ # for line item level discounts) or cart price (sum of all Product.OriginalSalePrice values) for cart level discounts. |
164
+ # | 2 | Fixed in original currency | Discount value specified in OriginalDiscountValue denotes the fixed value in the merchant’s
165
+ # currency. When calculating the discount’s DiscountValue, only the respective FX rate should be
166
+ # applied to OriginalDiscountValue. No other price modifications (such as country coefficient) should be performed. |
167
+ # | 3 | Fixed in customer currency | Discount value specified in DiscountValue denotes the fixed value nominated in the end
168
+ # customer’s currency that shouldn’t be affected by any price modifications (such as country coefficient). |
169
+ #
170
+ # return [Integer]
171
+ #
172
+ def calculation_mode
173
+ return 3 if order.fixed_pricing?
174
+ return 1 if free_gift?
175
+
176
+ amount_type = discount.try(:amount_type)
177
+ case amount_type
178
+ when :percent
179
+ 1
180
+ when :flat
181
+ 2
182
+ end
183
+ end
184
+
185
+ private
186
+
187
+ def free_gift?
188
+ GlobalE.free_gift_discount_types.include? discount.class.name
189
+ end
190
+
191
+ def pricing_sku
192
+ @pricing_sku ||= Pricing::Sku.find discount.sku rescue nil
193
+ end
194
+
195
+ def discount_promo_codes
196
+ discount.promo_codes + generated_codes
197
+ end
198
+
199
+ def order_promo_codes
200
+ order.promo_codes.reject(&:blank?).map(&:downcase)
201
+ end
202
+
203
+ def generated_codes
204
+ return [] unless code_list.present?
205
+
206
+ code_list.promo_codes.map(&:code)
207
+ end
208
+
209
+ def code_list
210
+ return unless discount.generated_codes_id
211
+ @generated_codes ||= CodeList.find(discount.generated_codes_id) rescue nil
212
+ end
213
+ end
214
+ end
215
+ end