spree_api 6.0.2 → 6.0.3
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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/spree/api/v3/admin/embed_permissions.rb +5 -2
- data/app/controllers/spree/api/v3/admin/products_controller.rb +56 -0
- data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +2 -1
- data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/import_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +8 -0
- data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +4 -1
- data/app/serializers/spree/api/v3/admin/promotion_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/return_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +3 -2
- data/app/serializers/spree/api/v3/admin/seller_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/fulfillment_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/seller/import_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/seller/product_serializer.rb +8 -0
- data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +3 -2
- data/config/initializers/typelizer.rb +8 -19
- data/config/routes.rb +5 -0
- data/lib/spree/api/admin_document.rb +284 -0
- data/lib/spree/api/agent_operations.rb +300 -0
- data/lib/spree/api/agent_resource_map.rb +32 -7
- data/lib/spree/api/agent_write_schemas.rb +15 -51
- data/lib/spree/api/engine.rb +14 -1
- data/lib/spree/api/enum_types.rb +4 -1
- data/lib/spree/api/openapi/schema_helper.rb +3 -3
- data/lib/spree/api/sdk_types.rb +190 -0
- data/lib/spree/api/sdk_types_task.rb +68 -0
- data/lib/spree/api/testing_support/agent_tools.rb +35 -0
- data/lib/spree/api/testing_support/agent_tools_contract.rb +110 -0
- data/lib/spree/api/testing_support/deterministic_openapi.rb +147 -0
- data/lib/spree/api/testing_support/filter_parameters.rb +99 -0
- data/lib/spree/api/testing_support/openapi.rb +232 -0
- data/lib/spree/api/testing_support/openapi_tasks.rb +21 -0
- data/lib/spree/api/typelizer_generation.rb +39 -11
- data/lib/tasks/openapi.rake +5 -0
- data/lib/tasks/sdk_types.rake +6 -0
- data/lib/typelizer/open_enums.rb +13 -1
- data/openapi/admin.yaml +1540 -33
- metadata +20 -9
- data/lib/spree/api/agent_workflow_endpoints.rb +0 -113
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3f1aae2e30afb2db5577e3315cd2779ab8f273bfa114b7e369f7c0c8a519214d
|
|
4
|
+
data.tar.gz: 15e89346921cf2a0f21bdccd6050e7f4854d0aea5d17d0ef666d853ea475f769
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 555454b4f93a2ec776ebd7a1c6ea407bbc359b10493768c838d29617b0d58011a024168a2f384c4e2ad21a983a2f31e3989afce90d864c6f272f5bc13b7253ae
|
|
7
|
+
data.tar.gz: 0f00cda28bba945fc65e7509cfd61bd5626af3c91957e2f6dea5819e078593a7aad38152e5439495019bfdaece73cfaf65751313a10604f6af4f864176f84cb1
|
|
@@ -13,7 +13,9 @@ module Spree
|
|
|
13
13
|
#
|
|
14
14
|
# Gift card codes are bearer credentials that ride along on every
|
|
15
15
|
# order, so serializers show them in full only to a caller who may read
|
|
16
|
-
# gift cards and masked to everyone else.
|
|
16
|
+
# gift cards and masked to everyone else. Customer records embedded in
|
|
17
|
+
# a rule (a promotion's or a price list's customer rule) are shown only
|
|
18
|
+
# to a caller who may read customers; the rule keeps its `customer_ids`.
|
|
17
19
|
module EmbedPermissions
|
|
18
20
|
extend ActiveSupport::Concern
|
|
19
21
|
|
|
@@ -44,7 +46,8 @@ module Spree
|
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def serializer_params
|
|
47
|
-
super.merge(gift_card_codes: holds_permission?('read_gift_cards')
|
|
49
|
+
super.merge(gift_card_codes: holds_permission?('read_gift_cards'),
|
|
50
|
+
customer_records: holds_permission?('read_customers'))
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
private
|
|
@@ -156,6 +156,28 @@ module Spree
|
|
|
156
156
|
run_review_workflow(Spree.product_reject_workflow, reason: params[:reason])
|
|
157
157
|
end
|
|
158
158
|
|
|
159
|
+
# PATCH /api/v3/admin/products/:id/activate
|
|
160
|
+
#
|
|
161
|
+
# Puts one product on sale.
|
|
162
|
+
def activate
|
|
163
|
+
run_status_workflow(Spree.product_activate_workflow, 'active')
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# PATCH /api/v3/admin/products/:id/archive
|
|
167
|
+
#
|
|
168
|
+
# Takes one product off sale, archived; activating it again puts it
|
|
169
|
+
# back on sale.
|
|
170
|
+
def archive
|
|
171
|
+
run_status_workflow(Spree.product_archive_workflow, 'archived')
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# PATCH /api/v3/admin/products/:id/draft
|
|
175
|
+
#
|
|
176
|
+
# Takes one product off sale, back to a draft.
|
|
177
|
+
def draft
|
|
178
|
+
run_status_workflow(Spree.product_draft_workflow, 'draft')
|
|
179
|
+
end
|
|
180
|
+
|
|
159
181
|
# POST /api/v3/admin/products/bulk_status_update
|
|
160
182
|
# Body: { ids: [...], status: 'draft' | 'active' | 'archived' }
|
|
161
183
|
def bulk_status_update
|
|
@@ -363,6 +385,40 @@ module Spree
|
|
|
363
385
|
|
|
364
386
|
private
|
|
365
387
|
|
|
388
|
+
# Unlike bulk_status_update, which writes the column, these run the
|
|
389
|
+
# status workflow, so its hooks and its event fire. A product in
|
|
390
|
+
# review is refused: its next status is a decision, made through
|
|
391
|
+
# approve or reject (docs/plans/6.0-seller-product-submission.md).
|
|
392
|
+
#
|
|
393
|
+
# A product already in that status is answered as it is: running the
|
|
394
|
+
# workflow again would publish its event again, and every webhook
|
|
395
|
+
# subscriber would see the move twice.
|
|
396
|
+
def run_status_workflow(workflow, status)
|
|
397
|
+
@resource = find_resource
|
|
398
|
+
authorize!(:update, @resource)
|
|
399
|
+
|
|
400
|
+
return render json: serialize_resource(@resource) if @resource.status == status
|
|
401
|
+
|
|
402
|
+
if @resource.in_review?
|
|
403
|
+
return render_error(
|
|
404
|
+
code: 'product_in_review',
|
|
405
|
+
message: I18n.t('spree.errors.messages.product_in_review'),
|
|
406
|
+
status: :unprocessable_content
|
|
407
|
+
)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# Not under a row lock taken here: that would wrap the workflow in
|
|
411
|
+
# a transaction, and it publishes its event once its own
|
|
412
|
+
# transaction is done, which an outer one would no longer be.
|
|
413
|
+
result = workflow.call(product: @resource)
|
|
414
|
+
|
|
415
|
+
if result.success?
|
|
416
|
+
render json: serialize_resource(@resource.reload)
|
|
417
|
+
else
|
|
418
|
+
render_service_error(@resource.errors.presence || result.error)
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
366
422
|
# Approving and rejecting are edits to the catalog, so they answer to
|
|
367
423
|
# the same key as any other product write.
|
|
368
424
|
def run_review_workflow(workflow, **arguments)
|
|
@@ -9,8 +9,6 @@ module Spree
|
|
|
9
9
|
full_name: [:string, nullable: true],
|
|
10
10
|
selected_locale: [:string, nullable: true],
|
|
11
11
|
avatar_url: [:string, nullable: true],
|
|
12
|
-
roles: 'Array<{ id: string; name: string }>',
|
|
13
|
-
stores: 'Array<{ id: string; name: string; code: string }>',
|
|
14
12
|
status: [:string, enum: Spree::AdminUserMethods::STATUSES, enum_type_name: 'AdminUserStatus'],
|
|
15
13
|
last_active_at: [:string, nullable: true],
|
|
16
14
|
inviter: ['Actor', nullable: true]
|
|
@@ -45,6 +43,7 @@ module Spree
|
|
|
45
43
|
# we fall back to `Spree::Current.store` if not.
|
|
46
44
|
# Filtered in Ruby rather than with `for_resource`, so the staff
|
|
47
45
|
# index's preloaded roles are used instead of a query per user.
|
|
46
|
+
typelize({ id: :string, name: :string }, multi: true)
|
|
48
47
|
attribute :roles do |user, params|
|
|
49
48
|
store = params&.dig(:store) || Spree::Current.store
|
|
50
49
|
roles = user.spree_roles.to_a
|
|
@@ -57,6 +56,7 @@ module Spree
|
|
|
57
56
|
# store switcher can offer all accessible stores. Read off the same
|
|
58
57
|
# preloaded roles, and deduped/sorted in Ruby, so the staff index
|
|
59
58
|
# spends no extra query per user.
|
|
59
|
+
typelize({ id: :string, name: :string, code: :string }, multi: true)
|
|
60
60
|
attribute :stores do |user|
|
|
61
61
|
stores = user.spree_roles.filter_map { |role| role.resource if role.resource.is_a?(Spree::Store) }
|
|
62
62
|
|
|
@@ -8,7 +8,6 @@ module Spree
|
|
|
8
8
|
digital: :boolean,
|
|
9
9
|
offers_pickup: :boolean, offers_shipping: :boolean,
|
|
10
10
|
stock_location_ids: [:string, multi: true],
|
|
11
|
-
origin_groups: ['Array<{ id: string; name: string | null; position: number | null; stock_location_ids: Array<string> }>'],
|
|
12
11
|
products_count: :number, delivery_methods_count: :number,
|
|
13
12
|
delivery_zones_count: :number
|
|
14
13
|
|
|
@@ -36,6 +35,8 @@ module Spree
|
|
|
36
35
|
|
|
37
36
|
# Origin groups partition the profile's fulfillment origins; zones
|
|
38
37
|
# and methods reference one. A null name renders as "All locations".
|
|
38
|
+
typelize({ id: :string, name: [:string, { nullable: true }], position: [:number, { nullable: true }],
|
|
39
|
+
stock_location_ids: 'string[]' }, multi: true)
|
|
39
40
|
attribute :origin_groups do |record|
|
|
40
41
|
record.delivery_origin_groups.map do |group|
|
|
41
42
|
{
|
|
@@ -17,7 +17,6 @@ module Spree
|
|
|
17
17
|
tax_total: [:string, nullable: false]
|
|
18
18
|
|
|
19
19
|
typelize metadata: 'Record<string, unknown>',
|
|
20
|
-
documents: "Array<{ kind: string; url: string }>",
|
|
21
20
|
provider_generates_labels: :boolean,
|
|
22
21
|
order_id: [:string, nullable: true],
|
|
23
22
|
stock_location_id: [:string, nullable: true]
|
|
@@ -31,6 +30,7 @@ module Spree
|
|
|
31
30
|
|
|
32
31
|
# Customs forms and other paperwork the provider produced beside the
|
|
33
32
|
# label; the labels themselves are listed under +labels+.
|
|
33
|
+
typelize({ kind: :string, url: :string }, multi: true)
|
|
34
34
|
attribute :documents do |fulfillment|
|
|
35
35
|
fulfillment.provider.documents(fulfillment).map(&:as_json)
|
|
36
36
|
end
|
|
@@ -10,7 +10,6 @@ module Spree
|
|
|
10
10
|
failed_rows_count: :number,
|
|
11
11
|
processing_errors: [:string, nullable: true],
|
|
12
12
|
delimiter: :string,
|
|
13
|
-
schema_fields: 'Array<{ name: string; label: string; required: boolean }>',
|
|
14
13
|
csv_headers: [:string, multi: true],
|
|
15
14
|
sample_row: 'Record<string, string | null>',
|
|
16
15
|
original_filename: [:string, nullable: true],
|
|
@@ -58,6 +57,7 @@ module Spree
|
|
|
58
57
|
import.rows_status_counts['failed'] || 0
|
|
59
58
|
end
|
|
60
59
|
|
|
60
|
+
typelize({ name: :string, label: :string, required: :boolean }, multi: true)
|
|
61
61
|
attribute :schema_fields do |import|
|
|
62
62
|
import.schema_fields.map do |field|
|
|
63
63
|
{ name: field[:name], label: field[:label], required: field[:required].present? }
|
|
@@ -13,8 +13,7 @@ module Spree
|
|
|
13
13
|
role_name: :string,
|
|
14
14
|
inviter_email: :string,
|
|
15
15
|
expires_at: :string,
|
|
16
|
-
invitee_exists: :boolean
|
|
17
|
-
store: '{ id: string; name: string }'
|
|
16
|
+
invitee_exists: :boolean
|
|
18
17
|
|
|
19
18
|
attributes :email, :status,
|
|
20
19
|
created_at: :iso8601, updated_at: :iso8601, expires_at: :iso8601
|
|
@@ -43,6 +42,7 @@ module Spree
|
|
|
43
42
|
# Minimal store identity for the unauthenticated acceptance page's
|
|
44
43
|
# title ("Join <store>"). Full Store would over-expose internals to
|
|
45
44
|
# a public landing page; this is the smallest shape that renders.
|
|
45
|
+
typelize({ id: :string, name: :string })
|
|
46
46
|
attribute :store do |invitation|
|
|
47
47
|
{ id: invitation.store.prefixed_id, name: invitation.store.name }
|
|
48
48
|
end
|
|
@@ -34,10 +34,12 @@ module Spree
|
|
|
34
34
|
resource: proc { Spree.api.admin_channel_serializer },
|
|
35
35
|
if: proc { |rule| rule.respond_to?(:channels) }
|
|
36
36
|
|
|
37
|
+
# Only for a caller who may read customers; see the promotion rule
|
|
38
|
+
# serializer.
|
|
37
39
|
many :users,
|
|
38
40
|
key: :customers,
|
|
39
41
|
resource: proc { Spree.api.admin_customer_serializer },
|
|
40
|
-
if: proc { |rule| rule.respond_to?(:users) }
|
|
42
|
+
if: proc { |rule| rule.respond_to?(:users) && params[:customer_records] }
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
end
|
|
@@ -17,6 +17,7 @@ module Spree
|
|
|
17
17
|
product_type_id: [:string, nullable: true],
|
|
18
18
|
delivery_profile_id: [:string, nullable: true],
|
|
19
19
|
seller_name: [:string, nullable: true],
|
|
20
|
+
total_on_hand: [:number, nullable: true],
|
|
20
21
|
price: ['Price', nullable: true],
|
|
21
22
|
deleted_at: [:string, nullable: true],
|
|
22
23
|
metadata: 'Record<string, unknown>',
|
|
@@ -49,6 +50,13 @@ module Spree
|
|
|
49
50
|
|
|
50
51
|
prefixed_id_attributes :product_type, :tax_category
|
|
51
52
|
|
|
53
|
+
# Null when any variant is not tracked: its stock is unlimited, which
|
|
54
|
+
# is not a number to send.
|
|
55
|
+
attribute :total_on_hand do |product|
|
|
56
|
+
total = product.total_on_hand
|
|
57
|
+
total.to_i unless total.infinite?
|
|
58
|
+
end
|
|
59
|
+
|
|
52
60
|
attribute :price do |product|
|
|
53
61
|
price = price_for(product.default_variant)
|
|
54
62
|
Spree.api.admin_price_serializer.new(price, params: params).to_h if price&.persisted?
|
|
@@ -13,8 +13,7 @@ module Spree
|
|
|
13
13
|
typelize type: [:string, comment: 'Action type. Built-in: create_adjustment, create_item_adjustments, create_line_items, free_shipping. Extensions may register more.'],
|
|
14
14
|
promotion_id: :string,
|
|
15
15
|
preferences: 'Record<string, unknown>',
|
|
16
|
-
calculator: 'TypedPromotionCalculator | null'
|
|
17
|
-
line_items: 'Array<{ variant_id: string; quantity: number }> | null'
|
|
16
|
+
calculator: 'TypedPromotionCalculator | null'
|
|
18
17
|
|
|
19
18
|
attributes created_at: :iso8601, updated_at: :iso8601
|
|
20
19
|
|
|
@@ -44,6 +43,7 @@ module Spree
|
|
|
44
43
|
# Line items the action will add for CreateLineItems. variant_id
|
|
45
44
|
# is prefixed for consistency with the rest of the API. Null on
|
|
46
45
|
# actions that don't have the association.
|
|
46
|
+
typelize({ variant_id: :string, quantity: :number }, multi: true, nullable: true)
|
|
47
47
|
attribute :line_items do |action|
|
|
48
48
|
next nil unless action.respond_to?(:promotion_action_line_items)
|
|
49
49
|
|
|
@@ -61,9 +61,12 @@ module Spree
|
|
|
61
61
|
resource: proc { Spree.api.admin_category_serializer },
|
|
62
62
|
if: proc { |rule| rule.respond_to?(:categories) }
|
|
63
63
|
|
|
64
|
+
# Only for a caller who may read customers: a promotion is readable
|
|
65
|
+
# under `read_promotions`, and a customer rule would otherwise carry
|
|
66
|
+
# every targeted customer's email and notes along with it.
|
|
64
67
|
many :customers,
|
|
65
68
|
resource: proc { Spree.api.admin_customer_serializer },
|
|
66
|
-
if: proc { |rule| rule.respond_to?(:customers) }
|
|
69
|
+
if: proc { |rule| rule.respond_to?(:customers) && params[:customer_records] }
|
|
67
70
|
|
|
68
71
|
many :customer_groups,
|
|
69
72
|
resource: proc { Spree.api.admin_customer_group_serializer },
|
|
@@ -34,6 +34,19 @@ module Spree
|
|
|
34
34
|
attribute :rule_ids do |promotion|
|
|
35
35
|
promotion.promotion_rules.map(&:prefixed_id)
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
# The rows under the same names the write accepts, on request: a
|
|
39
|
+
# reader holding only `rule_ids` cannot tell what a promotion does
|
|
40
|
+
# without a request per rule.
|
|
41
|
+
many :promotion_rules,
|
|
42
|
+
key: :rules,
|
|
43
|
+
resource: proc { Spree.api.admin_promotion_rule_serializer },
|
|
44
|
+
if: proc { expand?('rules') }
|
|
45
|
+
|
|
46
|
+
many :promotion_actions,
|
|
47
|
+
key: :actions,
|
|
48
|
+
resource: proc { Spree.api.admin_promotion_action_serializer },
|
|
49
|
+
if: proc { expand?('actions') }
|
|
37
50
|
end
|
|
38
51
|
end
|
|
39
52
|
end
|
|
@@ -11,7 +11,6 @@ module Spree
|
|
|
11
11
|
|
|
12
12
|
typelize memo: [:string, nullable: true],
|
|
13
13
|
metadata: 'Record<string, unknown>',
|
|
14
|
-
documents: "Array<{ kind: string; url: string }>",
|
|
15
14
|
stock_location_id: [:string, nullable: true],
|
|
16
15
|
created_by_id: [:string, nullable: true],
|
|
17
16
|
created_by_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
|
|
@@ -39,6 +38,7 @@ module Spree
|
|
|
39
38
|
|
|
40
39
|
# Paperwork the provider produced beside the label: a cross-border
|
|
41
40
|
# return is declared like any other export.
|
|
41
|
+
typelize({ kind: :string, url: :string }, multi: true)
|
|
42
42
|
attribute :documents do |return_record|
|
|
43
43
|
return_record.provider.documents(return_record).map(&:as_json)
|
|
44
44
|
end
|
|
@@ -14,10 +14,11 @@ module Spree
|
|
|
14
14
|
description: [:string, nullable: true],
|
|
15
15
|
required: :boolean, position: :number, status: [:string, enum: Spree::SellerRequirementStatus::STATUSES, enum_type_name: 'SellerRequirementState'],
|
|
16
16
|
blocking: :boolean, action_url: [:string, nullable: true],
|
|
17
|
-
blocker: ['{ state: string; message: string | null } | null'],
|
|
18
17
|
required_policy_name: [:string, nullable: true]
|
|
19
18
|
|
|
20
|
-
attributes :id, :kind, :name, :description, :required, :position, :status, :action_url
|
|
19
|
+
attributes :id, :kind, :name, :description, :required, :position, :status, :action_url
|
|
20
|
+
typelize({ state: :string, message: [:string, { nullable: true }] }, nullable: true)
|
|
21
|
+
attribute :blocker, &:blocker
|
|
21
22
|
|
|
22
23
|
# Whether this stands between the seller and approval. Serialized
|
|
23
24
|
# rather than left to each client to derive, so the dashboard's
|
|
@@ -20,7 +20,6 @@ module Spree
|
|
|
20
20
|
deleted_at: [:string, nullable: true],
|
|
21
21
|
on_holiday: :boolean, sellable: :boolean,
|
|
22
22
|
products_count: :number, users_count: :number,
|
|
23
|
-
onboarding_progress: '{ done: number; total: number }',
|
|
24
23
|
onboarding_complete: :boolean,
|
|
25
24
|
metadata: 'Record<string, unknown> | null'
|
|
26
25
|
|
|
@@ -63,7 +62,8 @@ module Spree
|
|
|
63
62
|
# requirements themselves, with their submissions, stay on the
|
|
64
63
|
# heavier `onboarding` action; a list of sellers needs the number,
|
|
65
64
|
# not the rows behind it.
|
|
66
|
-
|
|
65
|
+
typelize({ done: :number, total: :number })
|
|
66
|
+
attribute :onboarding_progress, &:onboarding_progress
|
|
67
67
|
|
|
68
68
|
attribute :onboarding_complete, &:onboarding_complete?
|
|
69
69
|
|
|
@@ -7,7 +7,6 @@ module Spree
|
|
|
7
7
|
fulfillment_type: [:string, enum: %w[shipping digital pickup pickup_point], enum_type_name: 'FulfillmentType'],
|
|
8
8
|
tracking: [:string, nullable: true], tracking_url: [:string, nullable: true],
|
|
9
9
|
fulfilled_at: [:string, nullable: true], delivered_at: [:string, nullable: true], unpriced: :boolean,
|
|
10
|
-
items: 'Array<{ item_id: string; variant_id: string; quantity: number }>',
|
|
11
10
|
pickup_point_data: ['Record<string, unknown>', nullable: true],
|
|
12
11
|
selected_delivery_rate_id: [:string, nullable: true]
|
|
13
12
|
|
|
@@ -40,6 +39,7 @@ module Spree
|
|
|
40
39
|
|
|
41
40
|
# Which items (and how many) are in this fulfillment.
|
|
42
41
|
# A line item can be split across fulfillments with different quantities.
|
|
42
|
+
typelize({ item_id: :string, variant_id: :string, quantity: :number }, multi: true)
|
|
43
43
|
attribute :items do |fulfillment|
|
|
44
44
|
fulfillment.manifest.filter_map do |item|
|
|
45
45
|
next unless item.line_item
|
|
@@ -16,7 +16,6 @@ module Spree
|
|
|
16
16
|
failed_rows_count: :number,
|
|
17
17
|
processing_errors: [:string, nullable: true],
|
|
18
18
|
delimiter: :string,
|
|
19
|
-
schema_fields: 'Array<{ name: string; label: string; required: boolean }>',
|
|
20
19
|
csv_headers: [:string, multi: true],
|
|
21
20
|
sample_row: 'Record<string, string | null>',
|
|
22
21
|
original_filename: [:string, nullable: true],
|
|
@@ -52,6 +51,7 @@ module Spree
|
|
|
52
51
|
import.rows_status_counts['failed'] || 0
|
|
53
52
|
end
|
|
54
53
|
|
|
54
|
+
typelize({ name: :string, label: :string, required: :boolean }, multi: true)
|
|
55
55
|
attribute :schema_fields do |import|
|
|
56
56
|
import.schema_fields.map do |field|
|
|
57
57
|
{ name: field[:name], label: field[:label], required: field[:required].present? }
|
|
@@ -7,8 +7,7 @@ module Spree
|
|
|
7
7
|
expires_at: [:string, nullable: true],
|
|
8
8
|
accepted_at: [:string, nullable: true],
|
|
9
9
|
inviter_email: :string,
|
|
10
|
-
invitee_exists: [:boolean, optional: true]
|
|
11
|
-
seller: '{ id: string; name: string }'
|
|
10
|
+
invitee_exists: [:boolean, optional: true]
|
|
12
11
|
|
|
13
12
|
attributes :email,
|
|
14
13
|
created_at: :iso8601, expires_at: :iso8601, accepted_at: :iso8601
|
|
@@ -29,6 +28,7 @@ module Spree
|
|
|
29
28
|
|
|
30
29
|
# The smallest shape the acceptance page's title ("Join <seller>")
|
|
31
30
|
# needs; the page is public, so nothing more of the seller goes out.
|
|
31
|
+
typelize({ id: :string, name: :string })
|
|
32
32
|
attribute :seller do |invitation|
|
|
33
33
|
{ id: invitation.resource.prefixed_id, name: invitation.resource.name }
|
|
34
34
|
end
|
|
@@ -18,12 +18,20 @@ module Spree
|
|
|
18
18
|
typelize status: [:string, enum: Spree::Product.statuses, enum_type_name: 'ProductStatus'], metadata: 'Record<string, unknown>',
|
|
19
19
|
product_type_id: [:string, nullable: true],
|
|
20
20
|
delivery_profile_id: [:string, nullable: true],
|
|
21
|
+
total_on_hand: [:number, nullable: true],
|
|
21
22
|
submission: ['ProductSubmission', nullable: true]
|
|
22
23
|
|
|
23
24
|
attributes :status, :metadata, created_at: :iso8601, updated_at: :iso8601
|
|
24
25
|
|
|
25
26
|
prefixed_id_attributes :product_type, :delivery_profile
|
|
26
27
|
|
|
28
|
+
# Null when any variant is not tracked: its stock is unlimited, which
|
|
29
|
+
# is not a number to send.
|
|
30
|
+
attribute :total_on_hand do |product|
|
|
31
|
+
total = product.total_on_hand
|
|
32
|
+
total.to_i unless total.infinite?
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
many :variants,
|
|
28
36
|
resource: proc { Spree.api.seller_variant_serializer },
|
|
29
37
|
if: proc { expand?('variants') }
|
|
@@ -10,13 +10,14 @@ module Spree
|
|
|
10
10
|
description: [:string, nullable: true],
|
|
11
11
|
required: :boolean, position: :number, status: [:string, enum: Spree::SellerRequirementStatus::STATUSES, enum_type_name: 'SellerRequirementState'],
|
|
12
12
|
blocking: :boolean, action_url: [:string, nullable: true],
|
|
13
|
-
blocker: ['{ state: string; message: string | null } | null'],
|
|
14
13
|
accepts_submissions: :boolean, requires_file: :boolean,
|
|
15
14
|
accepted_content_types: [:string, multi: true],
|
|
16
15
|
required_policy_name: [:string, nullable: true],
|
|
17
16
|
terms_html: [:string, nullable: true]
|
|
18
17
|
|
|
19
|
-
attributes :id, :kind, :name, :description, :required, :position, :status, :action_url
|
|
18
|
+
attributes :id, :kind, :name, :description, :required, :position, :status, :action_url
|
|
19
|
+
typelize({ state: :string, message: [:string, { nullable: true }] }, nullable: true)
|
|
20
|
+
attribute :blocker, &:blocker
|
|
20
21
|
|
|
21
22
|
attribute :blocking, &:blocking?
|
|
22
23
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
|
|
1
|
+
# Types are generated only by `bundle exec rake typelizer:generate`, which sets
|
|
2
|
+
# TYPELIZER=true before booting; the engine's `spree.api.typelizer` initializer
|
|
3
|
+
# keeps Typelizer from generating on its own.
|
|
4
|
+
|
|
5
|
+
require 'spree/api/typelizer_generation'
|
|
4
6
|
|
|
5
7
|
Rails.application.config.after_initialize do
|
|
6
8
|
api_root = Spree::Api::Engine.root
|
|
@@ -10,22 +12,11 @@ Rails.application.config.after_initialize do
|
|
|
10
12
|
config.comments = true
|
|
11
13
|
config.listen = false
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
# unmapped typed attributes crash generation.
|
|
15
|
-
config.plugin_configs = {
|
|
16
|
-
alba: {
|
|
17
|
-
ts_mapper: Typelizer::SerializerPlugins::Alba::ALBA_TS_MAPPER.merge(
|
|
18
|
-
'iso8601' => { type: :string },
|
|
19
|
-
'string' => { type: :string }
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
15
|
+
config.plugin_configs = Spree::Api::TypelizerGeneration.plugin_configs
|
|
23
16
|
|
|
24
17
|
# Serializers that exist only for the Admin API. Event serializers stay in:
|
|
25
18
|
# they describe the `data` of the typed webhook events the Store SDK ships.
|
|
26
|
-
store_excluded =
|
|
27
|
-
Asset CartPromotion OrderPromotion Report TaxCategory
|
|
28
|
-
].to_set
|
|
19
|
+
store_excluded = Spree::Api::TypelizerGeneration::STORE_EXCLUDED
|
|
29
20
|
|
|
30
21
|
# Store SDK — no prefix, package provides namespace
|
|
31
22
|
config.writer(:store) do |c|
|
|
@@ -74,9 +65,7 @@ Rails.application.config.after_initialize do
|
|
|
74
65
|
# branch; Category and CustomField are not, but the store product
|
|
75
66
|
# serializer this branch inherits references them, so their types still
|
|
76
67
|
# have to exist in the package.
|
|
77
|
-
store_nested_for_seller =
|
|
78
|
-
Category CustomField OptionType OptionValue Seller
|
|
79
|
-
].to_set
|
|
68
|
+
store_nested_for_seller = Spree::Api::TypelizerGeneration::SELLER_STORE_TYPES
|
|
80
69
|
|
|
81
70
|
config.writer(:seller) do |c|
|
|
82
71
|
c.output_dir = api_root.join('../../packages/seller-sdk/src/types/generated')
|
data/config/routes.rb
CHANGED
|
@@ -366,6 +366,11 @@ Spree::Core::Engine.add_routes do
|
|
|
366
366
|
# (docs/plans/6.0-seller-product-submission.md).
|
|
367
367
|
patch :approve
|
|
368
368
|
patch :reject
|
|
369
|
+
# One product's status, through the workflow that publishes its
|
|
370
|
+
# event; bulk_status_update writes the column for many at once.
|
|
371
|
+
patch :activate
|
|
372
|
+
patch :archive
|
|
373
|
+
patch :draft
|
|
369
374
|
end
|
|
370
375
|
collection do
|
|
371
376
|
post :bulk_status_update
|