spree_api 5.4.3 → 5.5.0.rc2

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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +36 -0
  3. data/app/controllers/concerns/spree/api/v3/admin/auth_cookies.rb +62 -0
  4. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +52 -0
  5. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +149 -0
  6. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +54 -0
  7. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +103 -0
  8. data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +60 -0
  9. data/app/controllers/concerns/spree/api/v3/error_handler.rb +4 -0
  10. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +84 -0
  11. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +104 -0
  12. data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +35 -1
  13. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +109 -0
  14. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +25 -0
  15. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +84 -0
  16. data/app/controllers/spree/api/v3/admin/auth_controller.rb +134 -0
  17. data/app/controllers/spree/api/v3/admin/base_controller.rb +3 -17
  18. data/app/controllers/spree/api/v3/admin/categories_controller.rb +25 -0
  19. data/app/controllers/spree/api/v3/admin/channels_controller.rb +65 -0
  20. data/app/controllers/spree/api/v3/admin/countries_controller.rb +38 -0
  21. data/app/controllers/spree/api/v3/admin/coupon_codes_controller.rb +33 -0
  22. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +34 -0
  23. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +129 -0
  24. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +31 -0
  25. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +83 -0
  26. data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +33 -0
  27. data/app/controllers/spree/api/v3/admin/customers/credit_cards_controller.rb +25 -0
  28. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +92 -0
  29. data/app/controllers/spree/api/v3/admin/customers_controller.rb +119 -0
  30. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +44 -0
  31. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +40 -0
  32. data/app/controllers/spree/api/v3/admin/exports_controller.rb +136 -0
  33. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +31 -0
  34. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +33 -0
  35. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +138 -0
  36. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +81 -0
  37. data/app/controllers/spree/api/v3/admin/markets_controller.rb +42 -0
  38. data/app/controllers/spree/api/v3/admin/me_controller.rb +69 -0
  39. data/app/controllers/spree/api/v3/admin/media_controller.rb +119 -0
  40. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +34 -0
  41. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +27 -0
  42. data/app/controllers/spree/api/v3/admin/orders/base_controller.rb +31 -0
  43. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +104 -0
  44. data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +79 -0
  45. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +92 -0
  46. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +90 -0
  47. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +53 -0
  48. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +59 -0
  49. data/app/controllers/spree/api/v3/admin/orders_controller.rb +190 -0
  50. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +73 -0
  51. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +179 -0
  52. data/app/controllers/spree/api/v3/admin/prices_controller.rb +157 -0
  53. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +48 -0
  54. data/app/controllers/spree/api/v3/admin/products_controller.rb +237 -0
  55. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +78 -0
  56. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +56 -0
  57. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +78 -0
  58. data/app/controllers/spree/api/v3/admin/resource_controller.rb +29 -11
  59. data/app/controllers/spree/api/v3/admin/roles_controller.rb +29 -0
  60. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +35 -0
  61. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +36 -0
  62. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +29 -0
  63. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +75 -0
  64. data/app/controllers/spree/api/v3/admin/store_controller.rb +53 -0
  65. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +21 -0
  66. data/app/controllers/spree/api/v3/admin/tags_controller.rb +51 -0
  67. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +21 -0
  68. data/app/controllers/spree/api/v3/admin/variants_controller.rb +33 -0
  69. data/app/controllers/spree/api/v3/admin/webhook_deliveries_controller.rb +49 -0
  70. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +75 -0
  71. data/app/controllers/spree/api/v3/resource_controller.rb +117 -8
  72. data/app/controllers/spree/api/v3/store/auth_controller.rb +8 -28
  73. data/app/controllers/spree/api/v3/store/base_controller.rb +6 -0
  74. data/app/controllers/spree/api/v3/store/carts_controller.rb +1 -0
  75. data/app/controllers/spree/api/v3/store/customers_controller.rb +6 -0
  76. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +77 -0
  77. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +2 -2
  78. data/app/controllers/spree/api/v3/store/products_controller.rb +4 -3
  79. data/app/controllers/spree/api/v3/store/resource_controller.rb +10 -2
  80. data/app/jobs/spree/webhook_delivery_job.rb +5 -0
  81. data/app/models/spree/api_key_ability.rb +16 -0
  82. data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -6
  83. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +3 -15
  84. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +19 -3
  85. data/app/serializers/spree/api/v3/admin/allowed_origin_serializer.rb +2 -6
  86. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +42 -0
  87. data/app/serializers/spree/api/v3/admin/category_serializer.rb +4 -3
  88. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -0
  89. data/app/serializers/spree/api/v3/admin/country_serializer.rb +1 -1
  90. data/app/serializers/spree/api/v3/admin/coupon_code_serializer.rb +30 -0
  91. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +4 -2
  92. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +21 -0
  93. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +8 -3
  94. data/app/serializers/spree/api/v3/admin/customer_group_serializer.rb +27 -0
  95. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +58 -2
  96. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +143 -0
  97. data/app/serializers/spree/api/v3/admin/export_serializer.rb +40 -0
  98. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +2 -6
  99. data/app/serializers/spree/api/v3/admin/{asset_serializer.rb → gift_card_batch_serializer.rb} +1 -1
  100. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +39 -4
  101. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +64 -0
  102. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +4 -16
  103. data/app/serializers/spree/api/v3/admin/media_serializer.rb +24 -2
  104. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +4 -1
  105. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +4 -1
  106. data/app/serializers/spree/api/v3/admin/order_serializer.rb +21 -6
  107. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +11 -2
  108. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +2 -6
  109. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +4 -1
  110. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +51 -0
  111. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +55 -0
  112. data/app/serializers/spree/api/v3/admin/price_serializer.rb +4 -0
  113. data/app/serializers/spree/api/v3/admin/product_publication_serializer.rb +11 -0
  114. data/app/serializers/spree/api/v3/admin/product_serializer.rb +34 -10
  115. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +71 -0
  116. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +85 -0
  117. data/app/serializers/spree/api/v3/admin/promotion_serializer.rb +41 -0
  118. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +4 -2
  119. data/app/serializers/spree/api/v3/admin/role_serializer.rb +17 -0
  120. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +16 -1
  121. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +11 -2
  122. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +46 -0
  123. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +37 -0
  124. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +19 -0
  125. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +11 -5
  126. data/app/serializers/spree/api/v3/admin/store_serializer.rb +55 -0
  127. data/app/serializers/spree/api/v3/admin/tax_category_serializer.rb +4 -2
  128. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +37 -6
  129. data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +45 -0
  130. data/app/serializers/spree/api/v3/admin/webhook_endpoint_serializer.rb +69 -0
  131. data/app/serializers/spree/api/v3/channel_serializer.rb +14 -0
  132. data/app/serializers/spree/api/v3/custom_field_serializer.rb +9 -10
  133. data/app/serializers/spree/api/v3/customer_serializer.rb +5 -0
  134. data/app/serializers/spree/api/v3/market_serializer.rb +2 -1
  135. data/app/serializers/spree/api/v3/media_serializer.rb +8 -6
  136. data/app/serializers/spree/api/v3/order_serializer.rb +6 -1
  137. data/app/serializers/spree/api/v3/payment_method_serializer.rb +11 -2
  138. data/app/serializers/spree/api/v3/product_publication_serializer.rb +22 -0
  139. data/app/serializers/spree/api/v3/product_serializer.rb +6 -1
  140. data/app/serializers/spree/api/v3/stock_reservation_serializer.rb +10 -0
  141. data/config/locales/en.yml +2 -0
  142. data/config/routes.rb +235 -1
  143. data/lib/spree/api/configuration.rb +2 -2
  144. data/lib/spree/api/dependencies.rb +25 -1
  145. data/lib/spree/api/openapi/path_sorter.rb +126 -0
  146. data/lib/spree/api/openapi/schema_helper.rb +185 -6
  147. data/lib/spree/api/testing_support/v3/base.rb +28 -0
  148. metadata +98 -8
  149. data/app/serializers/spree/api/v3/admin/shipping_category_serializer.rb +0 -14
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class AdjustmentsController < BaseController
7
+ scoped_resource :orders
8
+
9
+ protected
10
+
11
+ def model_class
12
+ Spree::Adjustment
13
+ end
14
+
15
+ def serializer_class
16
+ Spree.api.admin_adjustment_serializer
17
+ end
18
+
19
+ def parent_association
20
+ :adjustments
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class BaseController < ResourceController
7
+ include Spree::Api::V3::OrderLock
8
+
9
+ before_action :authorize_order_access!
10
+
11
+ protected
12
+
13
+ def set_parent
14
+ @parent = current_store.orders.find_by_prefix_id!(params[:order_id])
15
+ @order = @parent
16
+ end
17
+
18
+ # Read actions require only :show on the parent order; every write
19
+ # (create/update/destroy and custom member actions like capture,
20
+ # void, fulfill, split, apply gift card / store credit) requires
21
+ # :update, so a read-only role can't mutate an order it can view.
22
+ # Subclasses with custom read-only actions extend +read_actions+.
23
+ def authorize_order_access!
24
+ authorize_parent!(@parent)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,104 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class FulfillmentsController < BaseController
7
+ scoped_resource :fulfillments
8
+
9
+ before_action :set_resource, only: [:show, :update, :fulfill, :cancel, :resume, :split]
10
+
11
+ # PATCH /api/v3/admin/orders/:order_id/fulfillments/:id
12
+ def update
13
+ with_order_lock do
14
+ result = Spree.shipment_update_service.call(
15
+ shipment: @resource,
16
+ shipment_attributes: permitted_params.to_h
17
+ )
18
+
19
+ if result.success?
20
+ render json: serialize_resource(@resource.reload)
21
+ else
22
+ render_result_error(result)
23
+ end
24
+ end
25
+ end
26
+
27
+ # PATCH /api/v3/admin/orders/:order_id/fulfillments/:id/fulfill
28
+ def fulfill
29
+ with_order_lock do
30
+ @resource.ship!
31
+ render json: serialize_resource(@resource.reload)
32
+ rescue StateMachines::InvalidTransition => e
33
+ render_service_error(e.message)
34
+ end
35
+ end
36
+
37
+ # PATCH /api/v3/admin/orders/:order_id/fulfillments/:id/cancel
38
+ def cancel
39
+ with_order_lock do
40
+ @resource.cancel!
41
+ render json: serialize_resource(@resource.reload)
42
+ rescue StateMachines::InvalidTransition => e
43
+ render_service_error(e.message)
44
+ end
45
+ end
46
+
47
+ # PATCH /api/v3/admin/orders/:order_id/fulfillments/:id/resume
48
+ def resume
49
+ with_order_lock do
50
+ @resource.resume!
51
+ render json: serialize_resource(@resource.reload)
52
+ rescue StateMachines::InvalidTransition => e
53
+ render_service_error(e.message)
54
+ end
55
+ end
56
+
57
+ # PATCH /api/v3/admin/orders/:order_id/fulfillments/:id/split
58
+ def split
59
+ with_order_lock do
60
+ variant = Spree::Variant.find_by_prefix_id!(params[:variant_id])
61
+ quantity = params[:quantity].to_i
62
+
63
+ stock_location = if params[:stock_location_id].present?
64
+ Spree::StockLocation.find_by_prefix_id!(params[:stock_location_id])
65
+ else
66
+ @resource.stock_location
67
+ end
68
+
69
+ fulfilment_changer = @resource.transfer_to_location(variant, quantity, stock_location)
70
+
71
+ if fulfilment_changer.run!
72
+ fulfillments = @order.reload.shipments
73
+ render json: {
74
+ data: fulfillments.map { |s| serialize_resource(s) }
75
+ }
76
+ else
77
+ render_validation_error(fulfilment_changer.errors)
78
+ end
79
+ end
80
+ end
81
+
82
+ protected
83
+
84
+ def model_class
85
+ Spree::Shipment
86
+ end
87
+
88
+ def serializer_class
89
+ Spree.api.admin_fulfillment_serializer
90
+ end
91
+
92
+ def parent_association
93
+ :shipments
94
+ end
95
+
96
+ def permitted_params
97
+ params.permit(:tracking, :selected_shipping_rate_id, :stock_location_id, :state)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,79 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class GiftCardsController < BaseController
7
+ scoped_resource :gift_cards
8
+
9
+ skip_before_action :set_resource, raise: false
10
+
11
+ # POST /api/v3/admin/orders/:order_id/gift_cards
12
+ #
13
+ # Body: { code: String }
14
+ def create
15
+ with_order_lock do
16
+ gift_card = find_gift_card!
17
+ return unless gift_card
18
+
19
+ result = @parent.apply_gift_card(gift_card)
20
+
21
+ if result.success?
22
+ render json: serializer_class.new(gift_card).to_h, status: :created
23
+ else
24
+ render_service_error(result.error)
25
+ end
26
+ end
27
+ end
28
+
29
+ # DELETE /api/v3/admin/orders/:order_id/gift_cards/:id
30
+ def destroy
31
+ with_order_lock do
32
+ result = @parent.remove_gift_card
33
+
34
+ if result.success?
35
+ head :no_content
36
+ else
37
+ render_service_error(result.error)
38
+ end
39
+ end
40
+ end
41
+
42
+ protected
43
+
44
+ def model_class
45
+ Spree::GiftCard
46
+ end
47
+
48
+ def serializer_class
49
+ Spree.api.admin_gift_card_serializer
50
+ end
51
+
52
+ private
53
+
54
+ def find_gift_card!
55
+ gift_card = current_store.gift_cards.find_by(code: params[:code]&.downcase)
56
+
57
+ if gift_card.nil?
58
+ render_error(code: ERROR_CODES[:gift_card_not_found], message: Spree.t(:gift_card_not_found), status: :not_found)
59
+ return
60
+ end
61
+
62
+ if gift_card.expired?
63
+ render_error(code: ERROR_CODES[:gift_card_expired], message: Spree.t(:gift_card_expired), status: :unprocessable_content)
64
+ return
65
+ end
66
+
67
+ if gift_card.redeemed?
68
+ render_error(code: ERROR_CODES[:gift_card_already_redeemed], message: Spree.t(:gift_card_already_redeemed), status: :unprocessable_content)
69
+ return
70
+ end
71
+
72
+ gift_card
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,92 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class ItemsController < BaseController
7
+ scoped_resource :orders
8
+
9
+ # POST /api/v3/admin/orders/:order_id/items
10
+ def create
11
+ with_order_lock do
12
+ result = Spree.cart_add_item_service.call(
13
+ order: @parent,
14
+ variant: variant,
15
+ quantity: permitted_params[:quantity] || 1,
16
+ options: permitted_params[:options] || {}
17
+ )
18
+
19
+ if result.success?
20
+ render json: serialize_resource(result.value), status: :created
21
+ else
22
+ render_service_error(result.error, code: ERROR_CODES[:insufficient_stock])
23
+ end
24
+ end
25
+ end
26
+
27
+ # PATCH /api/v3/admin/orders/:order_id/items/:id
28
+ def update
29
+ with_order_lock do
30
+ if permitted_params[:quantity].present?
31
+ result = Spree.cart_set_item_quantity_service.call(
32
+ order: @parent,
33
+ line_item: @resource,
34
+ quantity: permitted_params[:quantity]
35
+ )
36
+
37
+ if result.success?
38
+ render json: serialize_resource(@resource.reload)
39
+ else
40
+ render_service_error(result.error, code: ERROR_CODES[:invalid_quantity])
41
+ end
42
+ else
43
+ if @resource.update(permitted_params.except(:variant_id, :quantity))
44
+ render json: serialize_resource(@resource)
45
+ else
46
+ render_errors(@resource.errors)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # DELETE /api/v3/admin/orders/:order_id/items/:id
53
+ def destroy
54
+ with_order_lock do
55
+ Spree.cart_remove_line_item_service.call(
56
+ order: @parent,
57
+ line_item: @resource
58
+ )
59
+
60
+ head :no_content
61
+ end
62
+ end
63
+
64
+ protected
65
+
66
+ def model_class
67
+ Spree::LineItem
68
+ end
69
+
70
+ def serializer_class
71
+ Spree.api.admin_line_item_serializer
72
+ end
73
+
74
+ def parent_association
75
+ :line_items
76
+ end
77
+
78
+ def permitted_params
79
+ params.permit(:variant_id, :quantity, metadata: {}, options: {})
80
+ end
81
+
82
+ private
83
+
84
+ def variant
85
+ @variant ||= current_store.variants.find_by_prefix_id!(permitted_params[:variant_id])
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,90 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class PaymentsController < BaseController
7
+ scoped_resource :payments
8
+
9
+ before_action :set_resource, only: [:show, :capture, :void]
10
+
11
+ # POST /api/v3/admin/orders/:order_id/payments
12
+ #
13
+ # Supports off-session admin charges by passing `source_id` referencing a
14
+ # saved payment source (e.g. a Spree::CreditCard owned by the order's customer).
15
+ # The source must belong to the customer assigned to the order.
16
+ def create
17
+ with_order_lock do
18
+ payment_method = Spree::PaymentMethod.find_by_prefix_id!(params[:payment_method_id])
19
+ @resource = @parent.payments.build(
20
+ amount: params[:amount] || @parent.order_total_after_store_credit,
21
+ payment_method: payment_method
22
+ )
23
+
24
+ if params[:source_id].present? && payment_method.source_required?
25
+ @resource.source = find_source!(payment_method, params[:source_id])
26
+ end
27
+
28
+ authorize_resource!(@resource, :create)
29
+
30
+ if @resource.save
31
+ render json: serialize_resource(@resource), status: :created
32
+ else
33
+ render_validation_error(@resource.errors)
34
+ end
35
+ end
36
+ end
37
+
38
+ # PATCH /api/v3/admin/orders/:order_id/payments/:id/capture
39
+ def capture
40
+ with_order_lock do
41
+ amount = params[:amount] ? (params[:amount].to_f * 100).round : nil
42
+ @resource.capture!(amount)
43
+ render json: serialize_resource(@resource.reload)
44
+ rescue Spree::Core::GatewayError => e
45
+ render_service_error(e.message)
46
+ end
47
+ end
48
+
49
+ # PATCH /api/v3/admin/orders/:order_id/payments/:id/void
50
+ def void
51
+ with_order_lock do
52
+ @resource.void_transaction!
53
+ render json: serialize_resource(@resource.reload)
54
+ rescue Spree::Core::GatewayError => e
55
+ render_service_error(e.message)
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ def model_class
62
+ Spree::Payment
63
+ end
64
+
65
+ def serializer_class
66
+ Spree.api.admin_payment_serializer
67
+ end
68
+
69
+ def parent_association
70
+ :payments
71
+ end
72
+
73
+ def permitted_params
74
+ params.permit(:amount, :payment_method_id, :source_id)
75
+ end
76
+
77
+ # Saved-source charges require an order customer — sources are scoped
78
+ # to that customer to prevent attaching customer A's card to
79
+ # customer B's order. Refuse if no customer is assigned.
80
+ def find_source!(payment_method, source_id)
81
+ raise ActiveRecord::RecordNotFound unless @parent.user
82
+
83
+ @parent.user.credit_cards.find_by_prefix_id!(source_id)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,53 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class RefundsController < BaseController
7
+ scoped_resource :refunds
8
+
9
+ # POST /api/v3/admin/orders/:order_id/refunds
10
+ def create
11
+ with_order_lock do
12
+ payment = @parent.payments.find_by_prefix_id!(params[:payment_id])
13
+ reason = Spree::RefundReason.find_by_prefix_id!(params[:refund_reason_id]) if params[:refund_reason_id].present?
14
+ reason ||= Spree::RefundReason.first
15
+
16
+ @resource = payment.refunds.build(
17
+ amount: params[:amount],
18
+ reason: reason,
19
+ transaction_id: nil
20
+ )
21
+ authorize_resource!(@resource, :create)
22
+
23
+ if @resource.save
24
+ render json: serialize_resource(@resource), status: :created
25
+ else
26
+ render_validation_error(@resource.errors)
27
+ end
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def model_class
34
+ Spree::Refund
35
+ end
36
+
37
+ def serializer_class
38
+ Spree.api.admin_refund_serializer
39
+ end
40
+
41
+ def scope
42
+ Spree::Refund.where(payment_id: @parent.payment_ids)
43
+ end
44
+
45
+ def collection_includes
46
+ [:payment, :reason]
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,59 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Orders
6
+ class StoreCreditsController < BaseController
7
+ scoped_resource :store_credits
8
+
9
+ skip_before_action :set_resource, raise: false
10
+
11
+ # POST /api/v3/admin/orders/:order_id/store_credits
12
+ #
13
+ # Body: { amount: Number (optional) }
14
+ #
15
+ # When `amount` is omitted, applies the customer's available store
16
+ # credit up to the order total.
17
+ def create
18
+ with_order_lock do
19
+ result = Spree.checkout_add_store_credit_service.call(
20
+ order: @parent,
21
+ amount: params[:amount].try(:to_f)
22
+ )
23
+
24
+ if result.success?
25
+ render json: serialize_resource(result.value), status: :created
26
+ else
27
+ render_service_error(result.error)
28
+ end
29
+ end
30
+ end
31
+
32
+ # DELETE /api/v3/admin/orders/:order_id/store_credits
33
+ def destroy
34
+ with_order_lock do
35
+ result = Spree.checkout_remove_store_credit_service.call(order: @parent)
36
+
37
+ if result.success?
38
+ head :no_content
39
+ else
40
+ render_service_error(result.error)
41
+ end
42
+ end
43
+ end
44
+
45
+ protected
46
+
47
+ def model_class
48
+ Spree::Order
49
+ end
50
+
51
+ def serializer_class
52
+ Spree.api.admin_order_serializer
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end