workarea-global_e 1.2.1

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 (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,122 @@
1
+ WORKAREA.registerModule('globalECheckoutInfoValidator', (function () {
2
+ var cartToken = function() {
3
+ return WORKAREA.cookie.read("GlobalECartId");
4
+ },
5
+
6
+ checkoutInfo = function() {
7
+ return $.getJSON(WORKAREA.routes.storefront.globalECheckoutCartInfoPath({cartToken: cartToken()}));
8
+ },
9
+
10
+ verifyProductPrices = function(product, discounts) {
11
+ var productContainer = $("[data-ge-basket-cartitemid='" + product.CartItemId + "']"),
12
+ salePrice, listPrice, subtotalPrice, totalPrice;
13
+
14
+ assertDom(productContainer, "Missing product container for " + product.CartItemId);
15
+
16
+ if (!_.isUndefined(productContainer.data('geBasketFreegift'))) {
17
+ return;
18
+ }
19
+
20
+ salePrice = $("[data-ge-basket-productsaleprice]", productContainer);
21
+ listPrice = $("[data-ge-basket-productlistprice]", productContainer);
22
+ subtotalPrice = $("[data-ge-basket-productsubtotalprice]", productContainer);
23
+ totalPrice = $("[data-ge-basket-producttotalprice]", productContainer);
24
+
25
+ assertDom(salePrice, "Missing sale price for " + product.Name + " : " + product.CartItemId);
26
+ assertPrice(salePrice, product.OriginalSalePrice);
27
+
28
+ assertDom(totalPrice, "Missing total price for " + product.Name + " : " + product.CartItemId);
29
+
30
+ if (product.OriginalListPrice === product.OriginalSalePrice) {
31
+ refuteDom(listPrice, "Expected not to find list price for " + product.Name + " : " + product.CartItemId);
32
+ } else {
33
+ assertDom(listPrice, "Expected to find list price for " + product.Name + " : " + product.CartItemId);
34
+ assertPrice(listPrice, product.OriginalListPrice);
35
+ }
36
+
37
+ _.forEach(productDiscounts(product.CartItemId, discounts), verifyProductDiscount);
38
+ if (productHasDiscounts(product.CartItemId, discounts)) {
39
+ assertDom(subtotalPrice, "Missing subtotalPrice " + product.Name + " : " + product.CartItemId);
40
+ assertPrice(subtotalPrice, product.OriginalSalePrice * product.OrderedQuantity);
41
+ } else {
42
+ refuteDom(subtotalPrice, "Expected not to find subtotalPrice for " + product.Name + " : " + product.CartItemId);
43
+ }
44
+ },
45
+
46
+ productDiscounts = function(cartItemId, discounts) {
47
+ return _.filter(discounts, { "ProductCartItemId": cartItemId });
48
+ },
49
+
50
+ verifyProductDiscount = function(discount) {
51
+ var discountPrice = $("[data-ge-basket-productdiscountsprice='" + discount.DiscountCode + "']");
52
+
53
+ assertDom(discountPrice, "Expected to find discount " + discount.name + " : " + discount.DiscountCode);
54
+ assertPrice(discountPrice, discount.OriginalDiscountValue);
55
+ },
56
+
57
+ productHasDiscounts = function(cartItemId, discounts) {
58
+ return !_.isUndefined(_.find(discounts, { "ProductCartItemId": cartItemId }));
59
+ },
60
+
61
+ verifyOrderPrices = function(products, discounts) {
62
+ var subtotal = $("[data-ge-basket-subtotals]"),
63
+ total = $("[data-ge-basket-totals]");
64
+
65
+ assertDom(subtotal, "Expected to find order subtotal");
66
+ assertDom(total, "Expected to find order total");
67
+
68
+ _.forEach(orderDiscounts(discounts), verifyOrderDiscount);
69
+ },
70
+
71
+ verifyOrderDiscount = function(discount) {
72
+ var element = $("[data-ge-basket-discounts='" + discount.DiscountCode + "']");
73
+
74
+ assertDom(element, "Expected to find order discount " + discount.Name + " : " + discount.DiscountCode);
75
+ assertPrice(element, discount.OriginalDiscountValue);
76
+ },
77
+
78
+ orderDiscounts = function(discounts) {
79
+ return _.filter(discounts, function(discount) { return _.isUndefined(discount.ProductCartItemId); });
80
+ },
81
+
82
+ assertDom = function(element, errorMessage) {
83
+ if (_.isEmpty(element)) {
84
+ throw errorMessage;
85
+ }
86
+ },
87
+
88
+ refuteDom = function(element, errorMessage) {
89
+ try {
90
+ assertDom(element, errorMessage);
91
+ throw errorMessage;
92
+ }
93
+ catch(error) { return true; }
94
+ },
95
+
96
+ assertPrice = function(element, expected) {
97
+ var actual = parseFloat(element.text().replace(/-?\$/, ""));
98
+ if (actual !== expected) {
99
+ throw "Expected " + actual + " to equal " + expected;
100
+ }
101
+ },
102
+
103
+ init = function() {
104
+ if (WORKAREA.url.parse(WORKAREA.url.current()).path !== "/cart") {
105
+ return;
106
+ }
107
+
108
+ checkoutInfo().done(function(cart) {
109
+ _.forEach(cart.productsList, function(product) {
110
+ verifyProductPrices(product, cart.discountsList);
111
+ });
112
+
113
+ if (!_.isEmpty(cart.productsList)) {
114
+ verifyOrderPrices(cart.productsList, cart.discountsList);
115
+ }
116
+ });
117
+ };
118
+
119
+ return {
120
+ init: init
121
+ };
122
+ }()));
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @namespace WORKAREA.global_e
3
+ */
4
+
5
+ WORKAREA.registerModule('global_e_price_filter', (function () {
6
+ var isOperatedByGlobalE = function() {
7
+ return WORKAREA.cookie.read('GlobalE_IsOperated') === "true";
8
+ },
9
+
10
+ init = function($scope) {
11
+ if (!isOperatedByGlobalE()) { return; }
12
+
13
+ $('.result-filters__section--price', $scope).hide();
14
+ };
15
+
16
+ return {
17
+ init: init
18
+ };
19
+ }()));
@@ -0,0 +1,67 @@
1
+ module Workarea
2
+ class Admin::CountryExceptionsController < Admin::ApplicationController
3
+ required_permissions :catalog
4
+ helper GlobalEHelpers
5
+
6
+ before_action :find_product
7
+ before_action :find_country_exception, except: [:index, :new]
8
+
9
+ def index
10
+ end
11
+
12
+ def new
13
+ @country_exception = GlobalE::CountryException.new
14
+ end
15
+
16
+ def create
17
+ if @country_exception.save
18
+ flash.now[:error] = t('workarea.admin.country_exceptions.flash_messages.saved')
19
+ redirect_to catalog_product_country_exceptions_path(@product)
20
+ else
21
+ @product.reload
22
+ flash.now[:error] = t('workarea.admin.country_exceptions.flash_messages.create_error')
23
+ render :new
24
+ end
25
+ end
26
+
27
+ def edit; end
28
+
29
+ def update
30
+ if @country_exception.update_attributes(country_exception_params)
31
+ flash[:success] = t('workarea.admin.country_exceptions.flash_messages.saved')
32
+ redirect_to catalog_product_country_exceptions_path(@product)
33
+ else
34
+ flash.now[:error] = t('workarea.admin.country_exceptions.flash_messages.update_error')
35
+ render :edit, status: :unprocessable_entity
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @country_exception.destroy
41
+
42
+ flash[:success] = t('workarea.admin.country_exceptions.flash_messages.deleted')
43
+ redirect_to catalog_product_country_exceptions_path(@product)
44
+ end
45
+
46
+ private
47
+
48
+ def find_product
49
+ model = Catalog::Product.find_by(slug: params[:catalog_product_id])
50
+ @product = Admin::ProductViewModel.new(model, view_model_options)
51
+ end
52
+
53
+ def find_country_exception
54
+ @country_exception ||= if params[:id].present?
55
+ @product.country_exceptions.find_or_create_by(id: params[:id])
56
+ else
57
+ @product.country_exceptions.build(country_exception_params)
58
+ end
59
+ end
60
+
61
+ def country_exception_params
62
+ @country_exception_params ||= params
63
+ .fetch(:country_exception, {})
64
+ .permit(:country, :restricted, :vat_rate)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,89 @@
1
+ module Workarea
2
+ module Admin
3
+ class FixedPricesController < ApplicationController
4
+ required_permissions :catalog
5
+ helper GlobalEHelpers
6
+
7
+ before_action :find_sku
8
+ before_action :find_price, except: [:index, :new]
9
+
10
+ def index
11
+ end
12
+
13
+ def new
14
+ @fixed_price = GlobalE::FixedPrice.new(fixed_price_params)
15
+ end
16
+
17
+ def create
18
+ if @fixed_price.save
19
+ flash[:success] = t('workarea.admin.fixed_prices.flash_messages.saved', sku: @sku.id)
20
+ redirect_to pricing_sku_fixed_prices_path(@sku)
21
+ else
22
+ @sku.reload
23
+ flash.now[:error] = t('workarea.admin.fixed_prices.flash_messages.create_error')
24
+ render :new
25
+ end
26
+ end
27
+
28
+ def edit
29
+ end
30
+
31
+ def update
32
+ if @fixed_price.update_attributes(fixed_price_params)
33
+ flash[:success] = t('workarea.admin.fixed_prices.flash_messages.saved', sku: @sku.id)
34
+ redirect_to pricing_sku_fixed_prices_path(@sku)
35
+ else
36
+ flash.now[:error] = t('workarea.admin.fixed_prices.flash_messages.update_error')
37
+ render :edit, status: :unprocessable_entity
38
+ end
39
+ end
40
+
41
+ def destroy
42
+ @fixed_price.destroy
43
+
44
+ flash[:success] = t('workarea.admin.fixed_prices.flash_messages.deleted', sku: @sku.id)
45
+ redirect_to pricing_sku_fixed_prices_path(@sku)
46
+ end
47
+
48
+ private
49
+
50
+ def fixed_price_params
51
+ @fixed_price_params ||=
52
+ begin
53
+ permitted = params.fetch(:fixed_price, {}).permit(:country, :currency_code, :sale, :regular, :active)
54
+ currency_code = permitted[:currency_code]
55
+
56
+ permitted[:regular] =
57
+ if permitted[:regular].present? && currency_code.present?
58
+ permitted[:regular].to_m(currency_code)
59
+ else
60
+ nil
61
+ end
62
+
63
+ permitted[:sale] =
64
+ if permitted[:sale].present? && currency_code.present?
65
+ permitted[:sale].to_m(currency_code)
66
+ else
67
+ nil
68
+ end
69
+
70
+ permitted
71
+ end
72
+ end
73
+
74
+ def find_sku
75
+ @sku = PricingSkuViewModel.wrap(
76
+ Pricing::Sku.find(params[:pricing_sku_id])
77
+ )
78
+ end
79
+
80
+ def find_price
81
+ @fixed_price = if params[:id].present?
82
+ @sku.fixed_prices.find_or_create_by(id: params[:id])
83
+ else
84
+ @sku.fixed_prices.build(fixed_price_params)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,6 @@
1
+ module Workarea
2
+ decorate Admin::OrdersController, with: :global_e do
3
+ def global_e
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,30 @@
1
+ module Workarea
2
+ decorate Storefront::ApplicationController, with: :global_e do
3
+ decorated do
4
+ after_action :set_global_e_cart_id_cookie
5
+ end
6
+
7
+ def current_order
8
+ @current_order ||= super.tap do |order|
9
+ order.assign_attributes(
10
+ currency: global_e_cookie["currencyCode"] || order.currency,
11
+ shipping_country: Country[global_e_cookie["countryISO"]] || order.shipping_country
12
+ )
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def global_e_cookie
19
+ @global_e_cookie ||= JSON.parse cookies[:GlobalE_Data] rescue {}
20
+ end
21
+
22
+ def set_global_e_cart_id_cookie
23
+ if current_order.persisted?
24
+ cookies["GlobalECartId"] = current_order.global_e_token
25
+ else
26
+ cookies.delete "GlobalECartId"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ module Workarea
2
+ decorate Storefront::CheckoutsController, with: :global_e do
3
+ decorated { before_action :route_global_e_order, if: :is_operated_by_global_e? }
4
+
5
+ private
6
+
7
+ def route_global_e_order
8
+ current_checkout.reset!
9
+ current_order.update_attributes(user_id: current_user.id) if current_user.present?
10
+ Pricing.perform(current_order)
11
+ redirect_to ge_checkout_path
12
+ end
13
+
14
+ def global_e_cookie
15
+ JSON.parse cookies[:GlobalE_Data] rescue {}
16
+ end
17
+
18
+ def is_operated_by_global_e?
19
+ cookies.fetch(:GlobalE_IsOperated, 'false').casecmp?('true')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ module Workarea
2
+ module Storefront
3
+ class GeCheckoutsController < Storefront::ApplicationController
4
+ layout 'workarea/storefront/checkout'
5
+
6
+ def show
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ module Workarea
2
+ module Storefront
3
+ class GlobalEController < ApplicationController
4
+ def get_checkout_cart_info
5
+ if checkout_cart_info_params[:countryCode].present? || checkout_cart_info_params[:MerchantGUID].present?
6
+ order.update_attribute(:checkout_started_at, Time.current)
7
+ end
8
+
9
+ if checkout_cart_info_params[:IsStockValidation]
10
+ InventoryAdjustment.new(order).tap(&:perform)
11
+ end
12
+
13
+ # GlobalE overriding fixed pricing for the order
14
+ #
15
+ if checkout_cart_info_params[:isFixedPriceSupported].present? &&
16
+ checkout_cart_info_params[:isFixedPriceSupported].to_s == "false"
17
+ order.update_attribute(:fixed_pricing, false)
18
+ end
19
+
20
+ render json: Workarea::GlobalE::CheckoutCartInfo.new(order).to_json
21
+ end
22
+
23
+ private
24
+
25
+ def order
26
+ @order ||= Order.find_by(
27
+ global_e_token: checkout_cart_info_params.require(:cartToken)
28
+ )
29
+ end
30
+
31
+ def checkout_cart_info_params
32
+ params.permit(
33
+ :cartToken,
34
+ :countryCode,
35
+ :IsStockValidation,
36
+ :MerchantGUID,
37
+ :isFixedPriceSupported
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,108 @@
1
+ module Workarea
2
+ module Storefront
3
+ module Globale
4
+ class ApiController < Storefront::ApplicationController
5
+ before_action :parse_merchant_order
6
+ before_action :validate_merchant_guid
7
+ before_action :find_order
8
+ after_action :log_api_event
9
+
10
+ rescue_from Exception, with: :api_error_response
11
+
12
+ # After this step is completed the order can be included in
13
+ # order history in the customer’s “My Account” section on the
14
+ # merchant’s site. It is also recommended to reserve the inventory
15
+ # for this order after the first step is completed, as long as usually
16
+ # the second step will follow too.
17
+ #
18
+ def receive_order
19
+ @response = GlobalE::Api::SendOrderToMerchant.new(@order, @merchant_order).response
20
+ render json: @response.to_json
21
+ end
22
+
23
+ # Posts order payment details for the order to the Merchant and performs
24
+ # the payment. Only order.OrderId and order.PaymentDetails members are
25
+ # mandatory for this method.
26
+ #
27
+ def receive_payment
28
+ @response = GlobalE::Api::PerformOrderPayment.new(@order, @merchant_order).response
29
+ render json: @response.to_json
30
+ end
31
+
32
+ def update_order_status
33
+ @response = GlobalE::Api::UpdateOrderStatus.new(@order, @merchant_order).response
34
+ render json: @response.to_json
35
+ end
36
+
37
+ # Updates order international shipping information on the Merchant’s
38
+ # site. Only order.OrderId and order.InternationalDetails members are
39
+ # mandatory for this method.
40
+ #
41
+ def receive_shipping_info
42
+ @response = GlobalE::Api::UpdateOrderShippingInfo.new(@order, @merchant_order).response
43
+ render json: @response.to_json
44
+ end
45
+
46
+ # Remove products from the order marked as restricted on Global-E's side.
47
+ def remove_restricted_products
48
+ @job = GlobalE::Api::RemoveRestrictedProducts.perform(
49
+ @order,
50
+ params['RemovedProductCodes']
51
+ )
52
+
53
+ render json: @job.response
54
+ end
55
+
56
+ private
57
+
58
+ def api_error_response(error)
59
+ GlobalE.report_error error
60
+ @response = GlobalE::Merchant::ResponseInfo.error(message: error.message, order: @order)
61
+ GlobalE::OrderApiEvents.upsert_one(
62
+ @order.id,
63
+ set: {
64
+ "#{params[:action]}" => @merchant_order.to_h,
65
+ "#{params[:action]}_response" => @response.to_h
66
+ }
67
+ )
68
+ render json: @response.to_json, status: :internal_server_error
69
+ end
70
+
71
+ def parse_merchant_order
72
+ @merchant_order = Workarea::GlobalE::Merchant::Order.new(
73
+ params.to_unsafe_hash.except(:controller, :action, :api)
74
+ )
75
+ end
76
+
77
+ def validate_merchant_guid
78
+ return if @merchant_order.merchant_guid == GlobalE.merchant_guid
79
+
80
+ head :bad_request
81
+ end
82
+
83
+ def find_order
84
+ @order ||=
85
+ if @merchant_order.cart_id.present?
86
+ Order.find_by(global_e_token: @merchant_order.cart_id)
87
+ elsif @merchant_order.merchant_order_id.present?
88
+ Order.find(@merchant_order.merchant_order_id)
89
+ elsif @merchant_order.order_id.present?
90
+ Order.find_by(global_e_id: @merchant_order.order_id)
91
+ end
92
+ end
93
+
94
+ def log_api_event
95
+ return unless @order && @response
96
+
97
+ GlobalE::OrderApiEvents.upsert_one(
98
+ @order.id,
99
+ set: {
100
+ "#{params[:action]}" => @merchant_order.to_h,
101
+ "#{params[:action]}_response" => @response.to_h
102
+ }
103
+ )
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,65 @@
1
+ module Workarea
2
+ module Storefront
3
+ module Globale
4
+ class RefundController < Storefront::ApplicationController
5
+ before_action :parse_order_refund
6
+ before_action :validate_merchant_guid
7
+ before_action :find_order
8
+ after_action :log_api_event
9
+
10
+ def receive_order_refund
11
+ @response = GlobalE::Api::NotifyOrderRefunded.new(@order, @order_refund).response
12
+ render json: @response.to_json
13
+ end
14
+
15
+ private
16
+
17
+ def api_error_response(error)
18
+ GlobalE.report_error error
19
+ @response = GlobalE::Merchant::ResponseInfo.error(message: error.message, order: @order)
20
+ GlobalE::OrderApiEvents.upsert_one(
21
+ @order.id,
22
+ set: {
23
+ "#{params[:action]}" => @order_refund.to_h,
24
+ "#{params[:action]}_response" => @response.to_h
25
+ }
26
+ )
27
+ render json: @response.to_json, status: :internal_server_error
28
+ end
29
+
30
+ def parse_order_refund
31
+ @order_refund = Workarea::GlobalE::Merchant::OrderRefund.new(
32
+ params.to_unsafe_hash.except(:controller, :action, :api)
33
+ )
34
+ end
35
+
36
+ def validate_merchant_guid
37
+ return if @order_refund.merchant_guid == GlobalE.merchant_guid
38
+
39
+ head :bad_request
40
+ end
41
+
42
+ def find_order
43
+ @order ||=
44
+ if @order_refund.merchant_order_id.present?
45
+ Order.find(@order_refund.merchant_order_id)
46
+ elsif @order_refund.order_id.present?
47
+ Order.find_by(global_e_id: @order_refund.order_id)
48
+ end
49
+ end
50
+
51
+ def log_api_event
52
+ return unless @order && @response
53
+
54
+ GlobalE::OrderApiEvents.upsert_one(
55
+ @order.id,
56
+ set: {
57
+ "#{params[:action]}" => @order_refund.to_h,
58
+ "#{params[:action]}_response" => @response.to_h
59
+ }
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ decorate Storefront::Users::LoginsController, with: :global_e do
3
+ decorated { after_action :set_global_e_culture_code_cookie }
4
+
5
+ private
6
+
7
+ def set_global_e_culture_code_cookie
8
+ return unless current_user&.global_e_culture_code.present?
9
+
10
+ cookies["GlobalECultureCode"] = current_user.global_e_culture_code
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ module Workarea
2
+ module Admin
3
+ module GlobalEHelpers
4
+ def currency_options(filtered_currencies = [])
5
+ filtered_currencies += [Money.default_currency]
6
+
7
+ [["---", nil]] + (all_currencies - filtered_currencies).map do |currency|
8
+ ["#{currency.name} (#{currency.symbol})", currency.iso_code]
9
+ end.compact
10
+ end
11
+
12
+ def global_e_country_options
13
+ [["---", nil]] + GlobalE.config.countries.map do |alpha2|
14
+ next unless country = Country[alpha2]
15
+ [country.name, alpha2]
16
+ end.compact
17
+ end
18
+
19
+ private
20
+
21
+ def all_currencies
22
+ @all_currencies ||= GlobalE.config.currencies.map do |iso_code|
23
+ Money::Currency.find iso_code
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ decorate Address, with: :global_e do
3
+ decorated do
4
+ field :skip_region_presence, type: Boolean
5
+ end
6
+
7
+ def region_presence
8
+ skip_region_presence || super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ decorate Catalog::Product, with: :global_e do
3
+ decorated do
4
+ field :global_e_forbidden, type: Boolean
5
+ embeds_many :country_exceptions,
6
+ class_name: "Workarea::GlobalE::CountryException",
7
+ inverse_of: :product
8
+ end
9
+
10
+ def global_e_forbidden
11
+ super || (Plugin.installed?(:gift_cards) && gift_card?)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ module Status
4
+ class PartiallyRefunded
5
+ include StatusCalculator::Status
6
+
7
+ def in_status?
8
+ order.items.any? { |i| i.quantity_refunded >= i.quantity }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end