From 5eab9e739919594ae7e7e416942ec93d84b699fd Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Thu, 16 Jan 2025 20:17:22 +0100 Subject: [PATCH] feat(promotion,dashboard,types,utils,medusa): Add statuses to promotions (#10950) what: - adds a status column to promotion table - introduce active promotion query - scope revert, register and compute actions to active promotions - admin to create and update promotion with statuses RESOLVES CMRC-845 RESOLVES CMRC-846 RESOLVES CMRC-847 RESOLVES CMRC-848 RESOLVES CMRC-849 RESOLVES CMRC-850 --- .changeset/long-tigers-sparkle.md | 9 + .../campaigns/admin/campaigns.spec.ts | 8 +- .../http/__tests__/cart/store/cart.spec.ts | 62 + .../promotions/admin/promotions.spec.ts | 99 +- .../cart/store/add-promotions-to-cart.spec.ts | 15 +- .../__tests__/cart/store/carts.spec.ts | 2 + .../store/remove-promotions-from-cart.spec.ts | 15 +- .../components/search/use-search-results.tsx | 2 +- .../promotion/status-cell/status-cell.tsx | 19 +- .../dashboard/src/hooks/api/campaigns.tsx | 4 +- .../src/i18n/translations/$schema.json | 2010 ++++------------- .../dashboard/src/i18n/translations/en.json | 16 +- .../admin/dashboard/src/lib/promotions.ts | 30 +- .../create-promotion-form.tsx | 59 +- .../create-promotion-form/form-schema.ts | 1 + .../promotion-general-section.tsx | 16 +- .../edit-promotion-details-form.tsx | 52 +- .../src/promotion/workflows/index.ts | 1 + .../workflows/update-promotions-status.ts | 55 + .../promotion/workflows/update-promotions.ts | 91 +- .../src/http/promotion/admin/payloads.ts | 2 + .../core/types/src/http/promotion/common.ts | 2 + .../types/src/promotion/common/promotion.ts | 44 +- packages/core/utils/src/promotion/index.ts | 6 + .../src/api/admin/promotions/query-config.ts | 1 + .../src/api/admin/promotions/validators.ts | 5 +- .../__fixtures__/promotion/index.ts | 7 +- .../promotion-module/compute-actions.spec.ts | 172 +- .../promotion-module/promotion.spec.ts | 21 +- .../promotion-module/register-usage.spec.ts | 11 +- .../promotion-module/revert-usage.spec.ts | 9 + .../.snapshot-medusa-promotion.json | 23 + .../src/migrations/Migration20250113094144.ts | 23 + .../modules/promotion/src/models/promotion.ts | 4 + .../src/services/promotion-module.ts | 55 +- 35 files changed, 1208 insertions(+), 1743 deletions(-) create mode 100644 .changeset/long-tigers-sparkle.md create mode 100644 packages/core/core-flows/src/promotion/workflows/update-promotions-status.ts create mode 100644 packages/modules/promotion/src/migrations/Migration20250113094144.ts diff --git a/.changeset/long-tigers-sparkle.md b/.changeset/long-tigers-sparkle.md new file mode 100644 index 0000000000..f526a66412 --- /dev/null +++ b/.changeset/long-tigers-sparkle.md @@ -0,0 +1,9 @@ +--- +"@medusajs/promotion": patch +"@medusajs/dashboard": patch +"@medusajs/types": patch +"@medusajs/utils": patch +"@medusajs/medusa": patch +--- + +feat(promotion,dashboard,types,utils,medusa): Add statuses to promotions diff --git a/integration-tests/http/__tests__/campaigns/admin/campaigns.spec.ts b/integration-tests/http/__tests__/campaigns/admin/campaigns.spec.ts index ca23a005f6..1ed253914e 100644 --- a/integration-tests/http/__tests__/campaigns/admin/campaigns.spec.ts +++ b/integration-tests/http/__tests__/campaigns/admin/campaigns.spec.ts @@ -1,5 +1,9 @@ -import { CampaignBudgetType, PromotionType } from "@medusajs/utils" import { medusaIntegrationTestRunner } from "@medusajs/test-utils" +import { + CampaignBudgetType, + PromotionStatus, + PromotionType, +} from "@medusajs/utils" import { createAdminUser } from "../../../../helpers/create-admin-user" jest.setTimeout(50000) @@ -46,6 +50,7 @@ export const campaignsData = [ const promotionData = { code: "TEST", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, is_automatic: true, application_method: { target_type: "items", @@ -108,6 +113,7 @@ medusaIntegrationTestRunner({ return { code, type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, is_automatic: true, application_method: { target_type: "items", diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index d8dde6d158..003f322c20 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -5,6 +5,7 @@ import { PriceListType, ProductStatus, PromotionRuleOperator, + PromotionStatus, PromotionType, } from "@medusajs/utils" import { @@ -176,6 +177,7 @@ medusaIntegrationTestRunner({ { code: "PROMOTION_APPLIED", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", @@ -488,6 +490,65 @@ medusaIntegrationTestRunner({ ) }) + it("should remove promotions when promotion is no longer in active state", async () => { + let responseBeforePromotionUpdate = await api.post( + `/store/carts/${cart.id}/line-items`, + { + variant_id: product.variants[0].id, + quantity: 1, + }, + storeHeaders + ) + + expect(responseBeforePromotionUpdate.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + items: expect.arrayContaining([ + expect.objectContaining({ + adjustments: [ + { + id: expect.any(String), + code: "PROMOTION_APPLIED", + promotion_id: promotion.id, + amount: 100, + }, + ], + }), + ]), + }) + ) + + await api.post( + `/admin/promotions/${promotion.id}`, + { status: PromotionStatus.INACTIVE }, + adminHeaders + ) + + let responseAfterPromotionUpdate = await api.post( + `/store/carts/${cart.id}/line-items`, + { + variant_id: product.variants[0].id, + quantity: 1, + }, + storeHeaders + ) + + expect(responseAfterPromotionUpdate.status).toEqual(200) + expect(responseAfterPromotionUpdate.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + items: expect.arrayContaining([ + expect.objectContaining({ + adjustments: [], + }), + expect.objectContaining({ + adjustments: [], + }), + ]), + }) + ) + }) + describe("with custom shipping options prices", () => { beforeEach(async () => { cart = ( @@ -1205,6 +1266,7 @@ medusaIntegrationTestRunner({ { code: "PROMOTION_TEST", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", diff --git a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts index c4edbafc69..f473d1f7b1 100644 --- a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts +++ b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts @@ -1,5 +1,5 @@ -import { PromotionType } from "@medusajs/utils" import { medusaIntegrationTestRunner } from "@medusajs/test-utils" +import { PromotionStatus, PromotionType } from "@medusajs/utils" import { createAdminUser } from "../../../../helpers/create-admin-user" jest.setTimeout(50000) @@ -8,6 +8,43 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } +const standardPromotionPayload = { + code: "TEST", + type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, + is_automatic: true, + campaign: { + name: "test", + campaign_identifier: "test-1", + budget: { + type: "usage", + limit: 100, + }, + }, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + currency_code: "USD", + value: 100, + max_quantity: 100, + target_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], +} + medusaIntegrationTestRunner({ testSuite: ({ dbConnection, getContainer, api }) => { describe("Admin Promotions API", () => { @@ -34,6 +71,7 @@ medusaIntegrationTestRunner({ { code: "TEST_ACROSS", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", allocation: "across", @@ -120,6 +158,7 @@ medusaIntegrationTestRunner({ { code: "first", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "order", @@ -183,41 +222,7 @@ medusaIntegrationTestRunner({ it("should create a standard promotion successfully", async () => { const response = await api.post( `/admin/promotions`, - { - code: "TEST", - type: PromotionType.STANDARD, - is_automatic: true, - campaign: { - name: "test", - campaign_identifier: "test-1", - budget: { - type: "usage", - limit: 100, - }, - }, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - currency_code: "USD", - value: 100, - max_quantity: 100, - target_rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, + standardPromotionPayload, adminHeaders ) @@ -275,6 +280,7 @@ medusaIntegrationTestRunner({ { code: "TEST", type: PromotionType.BUYGET, + status: PromotionStatus.ACTIVE, is_automatic: true, application_method: { target_type: "items", @@ -316,6 +322,7 @@ medusaIntegrationTestRunner({ { code: "TEST", type: PromotionType.BUYGET, + status: PromotionStatus.ACTIVE, is_automatic: true, application_method: { target_type: "items", @@ -356,6 +363,7 @@ medusaIntegrationTestRunner({ { code: "TEST", type: PromotionType.BUYGET, + status: PromotionStatus.ACTIVE, is_automatic: true, campaign: { name: "test", @@ -457,6 +465,23 @@ medusaIntegrationTestRunner({ }) ) }) + + it("should throw error when an incorrect status is passed", async () => { + const { response } = await api + .post( + `/admin/promotions`, + { ...standardPromotionPayload, status: "does-not-exist" }, + adminHeaders + ) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data).toEqual({ + type: "invalid_data", + message: + "Invalid request: Expected: 'draft, active, inactive' for field 'status', but got: 'does-not-exist'", + }) + }) }) describe("DELETE /admin/promotions/:id", () => { @@ -491,7 +516,7 @@ medusaIntegrationTestRunner({ expect(response.status).toEqual(404) expect(response.data.message).toEqual( - `Promotion with id "does-not-exist" not found` + `Promotion id not found: does-not-exist` ) }) diff --git a/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts b/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts index d44ec1b99c..866f93689d 100644 --- a/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts @@ -1,11 +1,12 @@ import { RemoteLink } from "@medusajs/modules-sdk" +import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { ICartModuleService, IPromotionModuleService } from "@medusajs/types" import { ContainerRegistrationKeys, Modules, + PromotionStatus, PromotionType, } from "@medusajs/utils" -import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { adminHeaders, createAdminUser, @@ -48,11 +49,12 @@ medusaIntegrationTestRunner({ await promotionModuleService.createPromotions({ code: "PROMOTION_APPLIED", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", allocation: "each", - value: "300", + value: 300, apply_to_quantity: 1, currency_code: "usd", max_quantity: 1, @@ -70,11 +72,12 @@ medusaIntegrationTestRunner({ await promotionModuleService.createPromotions({ code: "PROMOTION_TEST", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", allocation: "across", - value: "1000", + value: 1000, apply_to_quantity: 1, currency_code: "usd", target_rules: [ @@ -165,6 +168,7 @@ medusaIntegrationTestRunner({ { code: "PROMOTION_APPLIED", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, rules: [ { attribute: "customer_id", @@ -181,7 +185,7 @@ medusaIntegrationTestRunner({ type: "fixed", target_type: "shipping_methods", allocation: "each", - value: "100", + value: 100, max_quantity: 1, currency_code: "usd", target_rules: [ @@ -199,6 +203,7 @@ medusaIntegrationTestRunner({ { code: "PROMOTION_NEW", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, rules: [ { attribute: "customer_id", @@ -215,7 +220,7 @@ medusaIntegrationTestRunner({ type: "fixed", target_type: "shipping_methods", allocation: "each", - value: "200", + value: 200, max_quantity: 1, currency_code: "usd", target_rules: [ diff --git a/integration-tests/modules/__tests__/cart/store/carts.spec.ts b/integration-tests/modules/__tests__/cart/store/carts.spec.ts index a5b127746d..1c19c8cced 100644 --- a/integration-tests/modules/__tests__/cart/store/carts.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/carts.spec.ts @@ -19,6 +19,7 @@ import { MedusaError, Modules, ProductStatus, + PromotionStatus, PromotionType, } from "@medusajs/utils" import { @@ -1266,6 +1267,7 @@ medusaIntegrationTestRunner({ { code: "TEST", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, is_automatic: true, campaign: { campaign_identifier: "test", diff --git a/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts b/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts index e66b7f5916..b2e9f9e14d 100644 --- a/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts @@ -1,11 +1,12 @@ import { RemoteLink } from "@medusajs/modules-sdk" +import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { ICartModuleService, IPromotionModuleService } from "@medusajs/types" import { ContainerRegistrationKeys, Modules, + PromotionStatus, PromotionType, } from "@medusajs/utils" -import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { adminHeaders, createAdminUser, @@ -48,11 +49,12 @@ medusaIntegrationTestRunner({ await promotionModuleService.createPromotions({ code: "PROMOTION_APPLIED", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", allocation: "each", - value: "300", + value: 300, apply_to_quantity: 1, currency_code: "usd", max_quantity: 1, @@ -70,11 +72,12 @@ medusaIntegrationTestRunner({ await promotionModuleService.createPromotions({ code: "PROMOTION_APPLIED_TO_REMOVE", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, application_method: { type: "fixed", target_type: "items", allocation: "each", - value: "300", + value: 300, apply_to_quantity: 1, currency_code: "usd", max_quantity: 1, @@ -180,6 +183,7 @@ medusaIntegrationTestRunner({ const appliedPromotion = await promotionModuleService.createPromotions({ code: "PROMOTION_APPLIED", + status: PromotionStatus.ACTIVE, type: PromotionType.STANDARD, rules: [ { @@ -197,7 +201,7 @@ medusaIntegrationTestRunner({ type: "fixed", target_type: "shipping_methods", allocation: "each", - value: "100", + value: 100, max_quantity: 1, currency_code: "usd", target_rules: [ @@ -214,6 +218,7 @@ medusaIntegrationTestRunner({ await promotionModuleService.createPromotions({ code: "PROMOTION_APPLIED_TO_REMOVE", type: PromotionType.STANDARD, + status: PromotionStatus.ACTIVE, rules: [ { attribute: "customer_id", @@ -230,7 +235,7 @@ medusaIntegrationTestRunner({ type: "fixed", target_type: "shipping_methods", allocation: "each", - value: "100", + value: 100, max_quantity: 1, currency_code: "usd", target_rules: [ diff --git a/packages/admin/dashboard/src/components/search/use-search-results.tsx b/packages/admin/dashboard/src/components/search/use-search-results.tsx index 65312c5279..40a1a96f14 100644 --- a/packages/admin/dashboard/src/components/search/use-search-results.tsx +++ b/packages/admin/dashboard/src/components/search/use-search-results.tsx @@ -202,7 +202,7 @@ const useDynamicSearchResults = ( { q: debouncedSearch, limit, - fields: "id,code", + fields: "id,code,status", }, { enabled: isAreaEnabled(currentArea, "promotion"), diff --git a/packages/admin/dashboard/src/components/table/table-cells/promotion/status-cell/status-cell.tsx b/packages/admin/dashboard/src/components/table/table-cells/promotion/status-cell/status-cell.tsx index 13550527bf..6aed399848 100644 --- a/packages/admin/dashboard/src/components/table/table-cells/promotion/status-cell/status-cell.tsx +++ b/packages/admin/dashboard/src/components/table/table-cells/promotion/status-cell/status-cell.tsx @@ -1,28 +1,13 @@ import { HttpTypes } from "@medusajs/types" -import { useTranslation } from "react-i18next" -import { - getPromotionStatus, - PromotionStatus, -} from "../../../../../lib/promotions" +import { getPromotionStatus } from "../../../../../lib/promotions" import { StatusCell as StatusCell_ } from "../../common/status-cell" type PromotionCellProps = { promotion: HttpTypes.AdminPromotion } -type StatusColors = "grey" | "orange" | "green" | "red" -type StatusMap = Record export const StatusCell = ({ promotion }: PromotionCellProps) => { - const { t } = useTranslation() - - const statusMap: StatusMap = { - [PromotionStatus.DISABLED]: ["grey", t("statuses.disabled")], - [PromotionStatus.ACTIVE]: ["green", t("statuses.active")], - [PromotionStatus.SCHEDULED]: ["orange", t("statuses.scheduled")], - [PromotionStatus.EXPIRED]: ["red", t("statuses.expired")], - } - - const [color, text] = statusMap[getPromotionStatus(promotion)] + const [color, text] = getPromotionStatus(promotion) return {text} } diff --git a/packages/admin/dashboard/src/hooks/api/campaigns.tsx b/packages/admin/dashboard/src/hooks/api/campaigns.tsx index e34e0bff91..1657ab2d8f 100644 --- a/packages/admin/dashboard/src/hooks/api/campaigns.tsx +++ b/packages/admin/dashboard/src/hooks/api/campaigns.tsx @@ -1,3 +1,4 @@ +import { FetchError } from "@medusajs/js-sdk" import { HttpTypes, LinkMethodRequest } from "@medusajs/types" import { QueryKey, @@ -10,7 +11,6 @@ import { sdk } from "../../lib/client" import { queryClient } from "../../lib/query-client" import { queryKeysFactory } from "../../lib/query-key-factory" import { promotionsQueryKeys } from "./promotions" -import { FetchError } from "@medusajs/js-sdk" const REGIONS_QUERY_KEY = "campaigns" as const export const campaignsQueryKeys = queryKeysFactory(REGIONS_QUERY_KEY) @@ -88,6 +88,8 @@ export const useUpdateCampaign = ( onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: campaignsQueryKeys.lists() }) queryClient.invalidateQueries({ queryKey: campaignsQueryKeys.details() }) + queryClient.invalidateQueries({ queryKey: promotionsQueryKeys.lists() }) + queryClient.invalidateQueries({ queryKey: promotionsQueryKeys.details() }) options?.onSuccess?.(data, variables, context) }, diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index 698a73917d..951137b45f 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,11 +258,7 @@ "type": "string" } }, - "required": [ - "header_one", - "header_other", - "description" - ], + "required": ["header_one", "header_other", "description"], "additionalProperties": false } }, @@ -311,11 +307,7 @@ "type": "string" } }, - "required": [ - "insertRowAbove", - "insertRowBelow", - "deleteRow" - ], + "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], "additionalProperties": false }, "labels": { @@ -328,10 +320,7 @@ "type": "string" } }, - "required": [ - "key", - "value" - ], + "required": ["key", "value"], "additionalProperties": false }, "complexRow": { @@ -347,11 +336,7 @@ "type": "string" } }, - "required": [ - "label", - "description", - "tooltip" - ], + "required": ["label", "description", "tooltip"], "additionalProperties": false } }, @@ -366,12 +351,7 @@ "additionalProperties": false } }, - "required": [ - "header", - "numberOfKeys_one", - "numberOfKeys_other", - "edit" - ], + "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], "additionalProperties": false }, "validation": { @@ -384,10 +364,7 @@ "type": "string" } }, - "required": [ - "mustBeInt", - "mustBePositive" - ], + "required": ["mustBeInt", "mustBePositive"], "additionalProperties": false }, "actions": { @@ -573,9 +550,7 @@ "type": "string" } }, - "required": [ - "in" - ], + "required": ["in"], "additionalProperties": false }, "app": { @@ -926,12 +901,7 @@ "type": "string" } }, - "required": [ - "label", - "dark", - "light", - "system" - ], + "required": ["label", "dark", "light", "system"], "additionalProperties": false } }, @@ -954,10 +924,7 @@ "type": "string" } }, - "required": [ - "label", - "storeSettings" - ], + "required": ["label", "storeSettings"], "additionalProperties": false }, "actions": { @@ -967,17 +934,11 @@ "type": "string" } }, - "required": [ - "logout" - ], + "required": ["logout"], "additionalProperties": false } }, - "required": [ - "user", - "store", - "actions" - ], + "required": ["user", "store", "actions"], "additionalProperties": false }, "nav": { @@ -993,10 +954,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "common": { @@ -1006,9 +964,7 @@ "type": "string" } }, - "required": [ - "extensions" - ], + "required": ["extensions"], "additionalProperties": false }, "main": { @@ -1021,10 +977,7 @@ "type": "string" } }, - "required": [ - "store", - "storeSettings" - ], + "required": ["store", "storeSettings"], "additionalProperties": false }, "settings": { @@ -1043,30 +996,15 @@ "type": "string" } }, - "required": [ - "header", - "general", - "developer", - "myAccount" - ], + "required": ["header", "general", "developer", "myAccount"], "additionalProperties": false } }, - "required": [ - "accessibility", - "common", - "main", - "settings" - ], + "required": ["accessibility", "common", "main", "settings"], "additionalProperties": false } }, - "required": [ - "search", - "keyboardShortcuts", - "menus", - "nav" - ], + "required": ["search", "keyboardShortcuts", "menus", "nav"], "additionalProperties": false }, "dataGrid": { @@ -1085,11 +1023,7 @@ "type": "string" } }, - "required": [ - "view", - "resetToDefault", - "disabled" - ], + "required": ["view", "resetToDefault", "disabled"], "additionalProperties": false }, "shortcuts": { @@ -1183,10 +1117,7 @@ "additionalProperties": false } }, - "required": [ - "label", - "commands" - ], + "required": ["label", "commands"], "additionalProperties": false }, "errors": { @@ -1202,19 +1133,11 @@ "type": "string" } }, - "required": [ - "fixError", - "count_one", - "count_other" - ], + "required": ["fixError", "count_one", "count_other"], "additionalProperties": false } }, - "required": [ - "columns", - "shortcuts", - "errors" - ], + "required": ["columns", "shortcuts", "errors"], "additionalProperties": false }, "filters": { @@ -1300,11 +1223,7 @@ "type": "string" } }, - "required": [ - "date", - "compare", - "addFilter" - ], + "required": ["date", "compare", "addFilter"], "additionalProperties": false }, "errorBoundary": { @@ -1374,12 +1293,7 @@ "type": "string" } }, - "required": [ - "header", - "editHeader", - "editLabel", - "label" - ], + "required": ["header", "editHeader", "editLabel", "label"], "additionalProperties": false }, "billingAddress": { @@ -1438,11 +1352,7 @@ "type": "string" } }, - "required": [ - "editHeader", - "editLabel", - "label" - ], + "required": ["editHeader", "editLabel", "label"], "additionalProperties": false }, "transferOwnership": { @@ -1464,10 +1374,7 @@ "type": "string" } }, - "required": [ - "order", - "draft" - ], + "required": ["order", "draft"], "additionalProperties": false }, "currentOwner": { @@ -1480,10 +1387,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "newOwner": { @@ -1496,10 +1400,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "validation": { @@ -1512,10 +1413,7 @@ "type": "string" } }, - "required": [ - "mustBeDifferent", - "required" - ], + "required": ["mustBeDifferent", "required"], "additionalProperties": false } }, @@ -1536,9 +1434,7 @@ "type": "string" } }, - "required": [ - "availableIn" - ], + "required": ["availableIn"], "additionalProperties": false }, "products": { @@ -1554,9 +1450,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "edit": { @@ -1572,11 +1466,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "create": { @@ -1607,12 +1497,7 @@ "type": "string" } }, - "required": [ - "details", - "organize", - "variants", - "inventory" - ], + "required": ["details", "organize", "variants", "inventory"], "additionalProperties": false }, "errors": { @@ -1628,11 +1513,7 @@ "type": "string" } }, - "required": [ - "variants", - "options", - "uniqueSku" - ], + "required": ["variants", "options", "uniqueSku"], "additionalProperties": false }, "inventory": { @@ -1678,9 +1559,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "optionValues": { @@ -1690,9 +1569,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "productVariants": { @@ -1711,12 +1588,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "alert", - "tip" - ], + "required": ["label", "hint", "alert", "tip"], "additionalProperties": false }, "productOptions": { @@ -1729,10 +1601,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -1782,10 +1651,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "filters": { @@ -1798,10 +1664,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "columns": { @@ -1814,10 +1677,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1855,10 +1715,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "upload": { @@ -1899,10 +1756,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1996,11 +1850,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false }, "successToast": { @@ -2059,12 +1909,7 @@ "type": "string" } }, - "required": [ - "draft", - "published", - "proposed", - "rejected" - ], + "required": ["draft", "published", "proposed", "rejected"], "additionalProperties": false }, "fields": { @@ -2080,10 +1925,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "subtitle": { @@ -2093,9 +1935,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "handle": { @@ -2108,10 +1948,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "description": { @@ -2124,10 +1961,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "discountable": { @@ -2140,10 +1974,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "type": { @@ -2153,9 +1984,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "collection": { @@ -2165,9 +1994,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "categories": { @@ -2177,9 +2004,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "tags": { @@ -2189,9 +2014,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "sales_channels": { @@ -2204,10 +2027,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "countryOrigin": { @@ -2217,9 +2037,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "material": { @@ -2229,9 +2047,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "width": { @@ -2241,9 +2057,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "length": { @@ -2253,9 +2067,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "height": { @@ -2265,9 +2077,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "weight": { @@ -2277,9 +2087,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "options": { @@ -2328,10 +2136,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "mid_code": { @@ -2341,9 +2146,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "hs_code": { @@ -2353,9 +2156,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, @@ -2396,10 +2197,7 @@ "type": "string" } }, - "required": [ - "header", - "success" - ], + "required": ["header", "success"], "additionalProperties": false }, "create": { @@ -2409,9 +2207,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "deleteWarning": { @@ -2457,10 +2253,7 @@ "type": "string" } }, - "required": [ - "inventoryItems", - "inventoryKit" - ], + "required": ["inventoryItems", "inventoryKit"], "additionalProperties": false }, "inventoryKit": { @@ -2479,10 +2272,7 @@ "type": "string" } }, - "required": [ - "itemId", - "quantity" - ], + "required": ["itemId", "quantity"], "additionalProperties": false }, "header": { @@ -2577,10 +2367,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "create": { @@ -2593,22 +2380,14 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": [ - "header", - "edit", - "create", - "deleteWarning" - ], + "required": ["header", "edit", "create", "deleteWarning"], "additionalProperties": false }, "organization": { @@ -2630,23 +2409,15 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false } }, - "required": [ - "header", - "toasts" - ], + "required": ["header", "toasts"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "stock": { @@ -2694,10 +2465,7 @@ "type": "string" } }, - "required": [ - "header", - "description" - ], + "required": ["header", "description"], "additionalProperties": false }, "error": { @@ -2707,22 +2475,15 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } }, - "required": [ - "success", - "error" - ], + "required": ["success", "error"], "additionalProperties": false } }, - "required": [ - "delete" - ], + "required": ["delete"], "additionalProperties": false } }, @@ -2801,9 +2562,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -2816,10 +2575,7 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false }, "remove": { @@ -2832,18 +2588,11 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false } }, - "required": [ - "list", - "add", - "remove" - ], + "required": ["list", "add", "remove"], "additionalProperties": false } }, @@ -2891,22 +2640,14 @@ "type": "string" } }, - "required": [ - "details", - "organize" - ], + "required": ["details", "organize"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "tabs", - "successToast" - ], + "required": ["header", "hint", "tabs", "successToast"], "additionalProperties": false }, "edit": { @@ -2922,11 +2663,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "delete": { @@ -2939,10 +2676,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "products": { @@ -2999,17 +2733,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "remove", - "list" - ], + "required": ["add", "remove", "list"], "additionalProperties": false }, "organize": { @@ -3022,10 +2750,7 @@ "type": "string" } }, - "required": [ - "header", - "action" - ], + "required": ["header", "action"], "additionalProperties": false }, "fields": { @@ -3044,11 +2769,7 @@ "type": "string" } }, - "required": [ - "label", - "internal", - "public" - ], + "required": ["label", "internal", "public"], "additionalProperties": false }, "status": { @@ -3064,11 +2785,7 @@ "type": "string" } }, - "required": [ - "label", - "active", - "inactive" - ], + "required": ["label", "active", "inactive"], "additionalProperties": false }, "path": { @@ -3081,10 +2798,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "children": { @@ -3094,9 +2808,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "new": { @@ -3106,19 +2818,11 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, - "required": [ - "visibility", - "status", - "path", - "children", - "new" - ], + "required": ["visibility", "status", "path", "children", "new"], "additionalProperties": false } }, @@ -3268,10 +2972,7 @@ "type": "string" } }, - "required": [ - "noAvaliableQuantity", - "quantityOutOfRange" - ], + "required": ["noAvaliableQuantity", "quantityOutOfRange"], "additionalProperties": false } }, @@ -3307,15 +3008,11 @@ "type": "string" } }, - "required": [ - "stockedQuantity" - ], + "required": ["stockedQuantity"], "additionalProperties": false } }, - "required": [ - "errors" - ], + "required": ["errors"], "additionalProperties": false }, "toast": { @@ -3331,11 +3028,7 @@ "type": "string" } }, - "required": [ - "updateLocations", - "updateLevel", - "updateItem" - ], + "required": ["updateLocations", "updateLevel", "updateItem"], "additionalProperties": false }, "stock": { @@ -3482,9 +3175,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "create": { @@ -3500,11 +3191,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "groups": { @@ -3529,9 +3216,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -3547,16 +3232,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false }, "removed": { @@ -3572,16 +3252,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false } }, @@ -3609,11 +3284,7 @@ "type": "string" } }, - "required": [ - "header", - "emailDisabledTooltip", - "successToast" - ], + "required": ["header", "emailDisabledTooltip", "successToast"], "additionalProperties": false }, "delete": { @@ -3629,11 +3300,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "fields": { @@ -3649,11 +3316,7 @@ "type": "string" } }, - "required": [ - "guest", - "registered", - "groups" - ], + "required": ["guest", "registered", "groups"], "additionalProperties": false }, "registered": { @@ -3702,11 +3365,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -3719,10 +3378,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -3738,11 +3394,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "customers": { @@ -3767,17 +3419,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "successToast_one", - "successToast_other", - "list" - ], + "required": ["successToast_one", "successToast_other", "list"], "additionalProperties": false }, "remove": { @@ -3811,18 +3457,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "alreadyAddedTooltip", - "add", - "remove", - "list" - ], + "required": ["alreadyAddedTooltip", "add", "remove", "list"], "additionalProperties": false } }, @@ -3867,9 +3506,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "status": { @@ -4197,10 +3834,7 @@ "type": "string" } }, - "required": [ - "title", - "titlePending" - ], + "required": ["title", "titlePending"], "additionalProperties": false }, "toast": { @@ -4213,10 +3847,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "validation": { @@ -4226,9 +3857,7 @@ "type": "string" } }, - "required": [ - "quantityLowerThanFulfillment" - ], + "required": ["quantityLowerThanFulfillment"], "additionalProperties": false } }, @@ -4269,10 +3898,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "shippingAddress": { @@ -4285,10 +3911,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "billingAddress": { @@ -4301,18 +3924,11 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false } }, - "required": [ - "email", - "shippingAddress", - "billingAddress" - ], + "required": ["email", "shippingAddress", "billingAddress"], "additionalProperties": false }, "returns": { @@ -4418,10 +4034,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "placeholders": { @@ -4437,10 +4050,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false }, "outboundShippingOptions": { @@ -4453,10 +4063,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false } }, @@ -4541,10 +4148,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4557,10 +4161,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4649,15 +4250,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelClaim" - ], + "required": ["cancelClaim"], "additionalProperties": false }, "cancel": { @@ -4670,10 +4267,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4683,9 +4277,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4698,10 +4290,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4714,10 +4303,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4787,15 +4373,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelExchange" - ], + "required": ["cancelExchange"], "additionalProperties": false }, "cancel": { @@ -4808,10 +4390,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4821,9 +4400,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4836,10 +4413,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4852,10 +4426,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4889,10 +4460,7 @@ "type": "string" } }, - "required": [ - "allocatedLabel", - "notAllocatedLabel" - ], + "required": ["allocatedLabel", "notAllocatedLabel"], "additionalProperties": false }, "allocateItems": { @@ -4929,9 +4497,7 @@ "type": "string" } }, - "required": [ - "created" - ], + "required": ["created"], "additionalProperties": false }, "error": { @@ -4941,9 +4507,7 @@ "type": "string" } }, - "required": [ - "quantityNotAllocated" - ], + "required": ["quantityNotAllocated"], "additionalProperties": false } }, @@ -5066,11 +4630,7 @@ "type": "string" } }, - "required": [ - "wrongQuantity", - "wrongQuantity_other", - "noItems" - ], + "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], "additionalProperties": false }, "status": { @@ -5216,11 +4776,7 @@ "type": "string" } }, - "required": [ - "amountToLarge", - "amountNegative", - "reasonRequired" - ], + "required": ["amountToLarge", "amountNegative", "reasonRequired"], "additionalProperties": false } }, @@ -5316,10 +4872,7 @@ "type": "string" } }, - "required": [ - "toReturn", - "toSend" - ], + "required": ["toReturn", "toSend"], "additionalProperties": false }, "placed": { @@ -5332,10 +4885,7 @@ "type": "string" } }, - "required": [ - "title", - "fromSalesChannel" - ], + "required": ["title", "fromSalesChannel"], "additionalProperties": false }, "canceled": { @@ -5345,9 +4895,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "payment": { @@ -5366,12 +4914,7 @@ "type": "string" } }, - "required": [ - "awaiting", - "captured", - "canceled", - "refunded" - ], + "required": ["awaiting", "captured", "canceled", "refunded"], "additionalProperties": false }, "fulfillment": { @@ -5444,10 +4987,7 @@ "type": "string" } }, - "required": [ - "comment", - "byLine" - ], + "required": ["comment", "byLine"], "additionalProperties": false }, "claim": { @@ -5508,10 +5048,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed" - ], + "required": ["requested", "confirmed"], "additionalProperties": false }, "transfer": { @@ -5527,11 +5064,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed", - "declined" - ], + "required": ["requested", "confirmed", "declined"], "additionalProperties": false }, "update_order": { @@ -5547,11 +5080,7 @@ "type": "string" } }, - "required": [ - "shipping_address", - "billing_address", - "email" - ], + "required": ["shipping_address", "billing_address", "email"], "additionalProperties": false } }, @@ -5596,11 +5125,7 @@ "type": "string" } }, - "required": [ - "displayId", - "refundableAmount", - "returnableQuantity" - ], + "required": ["displayId", "refundableAmount", "returnableQuantity"], "additionalProperties": false } }, @@ -5661,11 +5186,7 @@ "type": "string" } }, - "required": [ - "label", - "warningTitle", - "warningDescription" - ], + "required": ["label", "warningTitle", "warningDescription"], "additionalProperties": false }, "status": { @@ -5678,10 +5199,7 @@ "type": "string" } }, - "required": [ - "open", - "completed" - ], + "required": ["open", "completed"], "additionalProperties": false }, "create": { @@ -5822,9 +5340,7 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false }, "create": { @@ -5840,11 +5356,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -5860,11 +5372,7 @@ "type": "string" } }, - "required": [ - "header", - "viewInventory", - "successToast" - ], + "required": ["header", "viewInventory", "successToast"], "additionalProperties": false }, "delete": { @@ -5874,9 +5382,7 @@ "type": "string" } }, - "required": [ - "confirmation" - ], + "required": ["confirmation"], "additionalProperties": false }, "fulfillmentProviders": { @@ -5925,9 +5431,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "shipping": { @@ -5937,9 +5441,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "disable": { @@ -5955,11 +5457,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "pickup", - "shipping" - ], + "required": ["confirmation", "pickup", "shipping"], "additionalProperties": false }, "enable": { @@ -5972,19 +5470,11 @@ "type": "string" } }, - "required": [ - "pickup", - "shipping" - ], + "required": ["pickup", "shipping"], "additionalProperties": false } }, - "required": [ - "pickup", - "shipping", - "disable", - "enable" - ], + "required": ["pickup", "shipping", "disable", "enable"], "additionalProperties": false }, "sidebar": { @@ -6003,17 +5493,11 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "header", - "shippingProfiles" - ], + "required": ["header", "shippingProfiles"], "additionalProperties": false }, "salesChannels": { @@ -6070,12 +5554,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "returns": { @@ -6094,12 +5573,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "tabs": { @@ -6112,22 +5586,14 @@ "type": "string" } }, - "required": [ - "details", - "prices" - ], + "required": ["details", "prices"], "additionalProperties": false }, "action": { "type": "string" } }, - "required": [ - "shipping", - "returns", - "tabs", - "action" - ], + "required": ["shipping", "returns", "tabs", "action"], "additionalProperties": false }, "delete": { @@ -6140,10 +5606,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "edit": { @@ -6159,11 +5622,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "successToast" - ], + "required": ["header", "action", "successToast"], "additionalProperties": false }, "pricing": { @@ -6173,9 +5632,7 @@ "type": "string" } }, - "required": [ - "action" - ], + "required": ["action"], "additionalProperties": false }, "conditionalPrices": { @@ -6194,9 +5651,7 @@ "type": "string" } }, - "required": [ - "cartItemTotal" - ], + "required": ["cartItemTotal"], "additionalProperties": false }, "summaries": { @@ -6212,11 +5667,7 @@ "type": "string" } }, - "required": [ - "range", - "greaterThan", - "lessThan" - ], + "required": ["range", "greaterThan", "lessThan"], "additionalProperties": false }, "actions": { @@ -6229,10 +5680,7 @@ "type": "string" } }, - "required": [ - "addPrice", - "manageConditionalPrices" - ], + "required": ["addPrice", "manageConditionalPrices"], "additionalProperties": false }, "rules": { @@ -6248,11 +5696,7 @@ "type": "string" } }, - "required": [ - "amount", - "gte", - "lte" - ], + "required": ["amount", "gte", "lte"], "additionalProperties": false }, "customRules": { @@ -6274,13 +5718,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "eq", - "gt", - "lt" - ], + "required": ["label", "tooltip", "eq", "gt", "lt"], "additionalProperties": false }, "errors": { @@ -6370,10 +5808,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "calculated": { @@ -6386,24 +5821,15 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, - "required": [ - "fixed", - "calculated" - ], + "required": ["fixed", "calculated"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "enableInStore": { @@ -6416,10 +5842,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "provider": { @@ -6490,10 +5913,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -6506,10 +5926,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "manageAreas": { @@ -6531,13 +5948,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "label", - "hint", - "successToast" - ], + "required": ["header", "action", "label", "hint", "successToast"], "additionalProperties": false }, "fields": { @@ -6550,20 +5961,11 @@ "type": "string" } }, - "required": [ - "noRecords", - "tip" - ], + "required": ["noRecords", "tip"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete", - "manageAreas", - "fields" - ], + "required": ["create", "edit", "delete", "manageAreas", "fields"], "additionalProperties": false } }, @@ -6604,11 +6006,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -6624,11 +6022,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "tooltip": { @@ -6638,19 +6032,11 @@ "type": "string" } }, - "required": [ - "type" - ], + "required": ["type"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "delete", - "tooltip" - ], + "required": ["domain", "subtitle", "create", "delete", "tooltip"], "additionalProperties": false }, "taxRegions": { @@ -6666,9 +6052,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false }, "delete": { @@ -6681,10 +6065,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -6706,22 +6087,14 @@ "type": "string" } }, - "required": [ - "rateIsRequired", - "nameIsRequired" - ], + "required": ["rateIsRequired", "nameIsRequired"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "errors", - "successToast" - ], + "required": ["header", "hint", "errors", "successToast"], "additionalProperties": false }, "province": { @@ -6740,17 +6113,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "state": { @@ -6769,17 +6136,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "stateOrTerritory": { @@ -6798,17 +6159,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "county": { @@ -6827,17 +6182,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "region": { @@ -6856,17 +6205,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "department": { @@ -6885,17 +6228,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "territory": { @@ -6914,17 +6251,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "prefecture": { @@ -6943,17 +6274,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "district": { @@ -6972,17 +6297,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "governorate": { @@ -7001,17 +6320,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "canton": { @@ -7030,17 +6343,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "emirate": { @@ -7059,17 +6366,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "sublevel": { @@ -7088,17 +6389,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "taxOverrides": { @@ -7117,10 +6412,7 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false }, "edit": { @@ -7133,18 +6425,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create", - "edit" - ], + "required": ["header", "create", "edit"], "additionalProperties": false }, "taxRates": { @@ -7163,11 +6448,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -7183,11 +6464,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -7200,18 +6477,11 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete" - ], + "required": ["create", "edit", "delete"], "additionalProperties": false }, "fields": { @@ -7233,12 +6503,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "true", - "false" - ], + "required": ["label", "hint", "true", "false"], "additionalProperties": false }, "defaultTaxRate": { @@ -7254,11 +6519,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "action" - ], + "required": ["label", "tooltip", "action"], "additionalProperties": false }, "taxRate": { @@ -7317,11 +6578,7 @@ "type": "string" } }, - "required": [ - "in", - "on", - "and" - ], + "required": ["in", "on", "and"], "additionalProperties": false }, "placeholders": { @@ -7387,9 +6644,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "values_one": { @@ -7561,10 +6816,7 @@ "type": "string" } }, - "required": [ - "sublevel", - "notPartOfCountry" - ], + "required": ["sublevel", "notPartOfCountry"], "additionalProperties": false }, "alert": { @@ -7580,20 +6832,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false } }, - "required": [ - "labels", - "placeholders", - "tooltips", - "alert" - ], + "required": ["labels", "placeholders", "tooltips", "alert"], "additionalProperties": false }, "noDefaultRate": { @@ -7606,10 +6849,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false } }, @@ -7662,9 +6902,7 @@ "type": "string" } }, - "required": [ - "details" - ], + "required": ["details"], "additionalProperties": false }, "tabs": { @@ -7680,11 +6918,7 @@ "type": "string" } }, - "required": [ - "template", - "details", - "campaign" - ], + "required": ["template", "details", "campaign"], "additionalProperties": false }, "fields": { @@ -7721,9 +6955,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "conditions": { @@ -7739,10 +6971,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "target-rules": { @@ -7755,10 +6984,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buy-rules": { @@ -7771,18 +6997,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "rules", - "target-rules", - "buy-rules" - ], + "required": ["rules", "target-rules", "buy-rules"], "additionalProperties": false } }, @@ -7807,9 +7026,7 @@ "type": "string" } }, - "required": [ - "campaignType" - ], + "required": ["campaignType"], "additionalProperties": false }, "errors": { @@ -7822,10 +7039,7 @@ "type": "string" } }, - "required": [ - "requiredField", - "promotionTabError" - ], + "required": ["requiredField", "promotionTabError"], "additionalProperties": false }, "toasts": { @@ -7835,9 +7049,7 @@ "type": "string" } }, - "required": [ - "promotionCreateSuccess" - ], + "required": ["promotionCreateSuccess"], "additionalProperties": false }, "create": { @@ -7859,9 +7071,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "target-rules": { @@ -7871,9 +7081,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "buy-rules": { @@ -7883,18 +7091,11 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false } }, - "required": [ - "title", - "rules", - "target-rules", - "buy-rules" - ], + "required": ["title", "rules", "target-rules", "buy-rules"], "additionalProperties": false }, "campaign": { @@ -7913,10 +7114,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "actions": { @@ -7926,17 +7124,11 @@ "type": "string" } }, - "required": [ - "goToCampaign" - ], + "required": ["goToCampaign"], "additionalProperties": false } }, - "required": [ - "header", - "edit", - "actions" - ], + "required": ["header", "edit", "actions"], "additionalProperties": false }, "campaign_currency": { @@ -7946,9 +7138,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "form": { @@ -7985,18 +7175,11 @@ "type": "string" } }, - "required": [ - "title", - "desc" - ], + "required": ["title", "desc"], "additionalProperties": false } }, - "required": [ - "title", - "description", - "placeholder" - ], + "required": ["title", "description", "placeholder"], "additionalProperties": false }, "new": { @@ -8009,10 +7192,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "none": { @@ -8025,29 +7205,66 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "existing", - "new", - "none" - ], + "required": ["existing", "new", "none"], "additionalProperties": false }, "status": { "type": "object", "properties": { - "title": { + "label": { "type": "string" + }, + "draft": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": ["title", "description"], + "additionalProperties": false + }, + "active": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": ["title", "description"], + "additionalProperties": false + }, + "inactive": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": ["title", "description"], + "additionalProperties": false } }, "required": [ - "title" + "label", + "draft", + "active", + "inactive", + "enabled", + "disabled" ], "additionalProperties": false }, @@ -8067,10 +7284,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "automatic": { @@ -8083,18 +7297,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "label", - "code", - "automatic" - ], + "required": ["label", "code", "automatic"], "additionalProperties": false }, "max_quantity": { @@ -8107,10 +7314,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "type": { @@ -8126,10 +7330,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buyget": { @@ -8142,17 +7343,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "standard", - "buyget" - ], + "required": ["standard", "buyget"], "additionalProperties": false }, "allocation": { @@ -8168,10 +7363,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "across": { @@ -8184,17 +7376,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "each", - "across" - ], + "required": ["each", "across"], "additionalProperties": false }, "code": { @@ -8207,10 +7393,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "value": { @@ -8220,9 +7403,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "value_type": { @@ -8238,10 +7419,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "percentage": { @@ -8254,17 +7432,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "fixed", - "percentage" - ], + "required": ["fixed", "percentage"], "additionalProperties": false } }, @@ -8306,16 +7478,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "list" - ], + "required": ["add", "list"], "additionalProperties": false } }, @@ -8361,11 +7528,7 @@ "type": "string" } }, - "required": [ - "active", - "expired", - "scheduled" - ], + "required": ["active", "expired", "scheduled"], "additionalProperties": false }, "delete": { @@ -8381,11 +7544,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "edit": { @@ -8401,11 +7560,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "configuration": { @@ -8427,18 +7582,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "create": { @@ -8500,9 +7648,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false } }, @@ -8531,10 +7677,7 @@ "type": "string" } }, - "required": [ - "hint", - "header" - ], + "required": ["hint", "header"], "additionalProperties": false }, "details": { @@ -8556,12 +7699,7 @@ "type": "string" } }, - "required": [ - "type", - "currency", - "limit", - "used" - ], + "required": ["type", "currency", "limit", "used"], "additionalProperties": false }, "type": { @@ -8577,10 +7715,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "usage": { @@ -8593,17 +7728,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "spend", - "usage" - ], + "required": ["spend", "usage"], "additionalProperties": false }, "edit": { @@ -8613,19 +7742,11 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } }, - "required": [ - "create", - "details", - "fields", - "type", - "edit" - ], + "required": ["create", "details", "fields", "type", "edit"], "additionalProperties": false }, "promotions": { @@ -8641,10 +7762,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "alreadyAdded": { @@ -8663,9 +7781,7 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false }, "add": { @@ -8678,15 +7794,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "list": { @@ -8696,9 +7808,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -8755,10 +7865,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -8783,11 +7890,7 @@ "type": "string" } }, - "required": [ - "details", - "products", - "prices" - ], + "required": ["details", "products", "prices"], "additionalProperties": false }, "successToast": { @@ -8803,15 +7906,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, @@ -8834,10 +7933,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "configuration": { @@ -8859,18 +7955,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "products": { @@ -8889,10 +7978,7 @@ "type": "string" } }, - "required": [ - "addProducts", - "editPrices" - ], + "required": ["addProducts", "editPrices"], "additionalProperties": false }, "delete": { @@ -8926,9 +8012,7 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false }, "edit": { @@ -8938,19 +8022,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "header", - "actions", - "delete", - "add", - "edit" - ], + "required": ["header", "actions", "delete", "add", "edit"], "additionalProperties": false }, "fields": { @@ -8966,10 +8042,7 @@ "type": "string" } }, - "required": [ - "label", - "header" - ], + "required": ["label", "header"], "additionalProperties": false }, "status": { @@ -8994,19 +8067,11 @@ "type": "string" } }, - "required": [ - "active", - "draft", - "expired", - "scheduled" - ], + "required": ["active", "draft", "expired", "scheduled"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "type": { @@ -9031,10 +8096,7 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false }, "override": { @@ -9047,25 +8109,15 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "sale", - "override" - ], + "required": ["sale", "override"], "additionalProperties": false } }, - "required": [ - "label", - "hint", - "options" - ], + "required": ["label", "hint", "options"], "additionalProperties": false }, "startsAt": { @@ -9078,10 +8130,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "endsAt": { @@ -9094,10 +8143,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "customerAvailability": { @@ -9171,10 +8217,7 @@ "type": "string" } }, - "required": [ - "languageLabel", - "usageInsightsLabel" - ], + "required": ["languageLabel", "usageInsightsLabel"], "additionalProperties": false }, "edit": { @@ -9208,9 +8251,7 @@ "type": "string" } }, - "required": [ - "edit" - ], + "required": ["edit"], "additionalProperties": false } }, @@ -9275,11 +8316,7 @@ "type": "string" } }, - "required": [ - "accepted", - "pending", - "expired" - ], + "required": ["accepted", "pending", "expired"], "additionalProperties": false }, "roles": { @@ -9295,11 +8332,7 @@ "type": "string" } }, - "required": [ - "admin", - "developer", - "member" - ], + "required": ["admin", "developer", "member"], "additionalProperties": false }, "deleteUserWarning": { @@ -9384,9 +8417,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "toast": { @@ -9508,9 +8539,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "toast": { @@ -9529,12 +8558,7 @@ "type": "string" } }, - "required": [ - "delete", - "edit", - "create", - "countries" - ], + "required": ["delete", "edit", "create", "countries"], "additionalProperties": false }, "shippingOption": { @@ -9568,12 +8592,7 @@ "type": "string" } }, - "required": [ - "outbound", - "outboundHint", - "return", - "returnHint" - ], + "required": ["outbound", "outboundHint", "return", "returnHint"], "additionalProperties": false }, "priceType": { @@ -9589,11 +8608,7 @@ "type": "string" } }, - "required": [ - "label", - "flatRate", - "calculated" - ], + "required": ["label", "flatRate", "calculated"], "additionalProperties": false }, "availability": { @@ -9606,10 +8621,7 @@ "type": "string" } }, - "required": [ - "adminOnly", - "adminOnlyHint" - ], + "required": ["adminOnly", "adminOnlyHint"], "additionalProperties": false }, "taxInclusiveHint": { @@ -9625,10 +8637,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -9690,9 +8699,7 @@ "type": "string" } }, - "required": [ - "taxCountriesHint" - ], + "required": ["taxCountriesHint"], "additionalProperties": false }, "settings": { @@ -9746,9 +8753,7 @@ "type": "string" } }, - "required": [ - "sectionTitle" - ], + "required": ["sectionTitle"], "additionalProperties": false }, "taxRate": { @@ -9898,11 +8903,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "removeChannel" - ], + "required": ["create", "update", "removeChannel"], "additionalProperties": false } }, @@ -9932,11 +8933,7 @@ "type": "string" } }, - "required": [ - "domain", - "subtitle", - "deleteWarning" - ], + "required": ["domain", "subtitle", "deleteWarning"], "additionalProperties": false }, "salesChannels": { @@ -9988,11 +8985,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "delete" - ], + "required": ["create", "update", "delete"], "additionalProperties": false }, "tooltip": { @@ -10002,9 +8995,7 @@ "type": "string" } }, - "required": [ - "cannotDeleteDefault" - ], + "required": ["cannotDeleteDefault"], "additionalProperties": false }, "products": { @@ -10017,9 +9008,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -10032,22 +9021,15 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, - "required": [ - "list", - "add" - ], + "required": ["list", "add"], "additionalProperties": false } }, @@ -10082,10 +9064,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "subtitle": { @@ -10098,10 +9077,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "status": { @@ -10114,10 +9090,7 @@ "type": "string" } }, - "required": [ - "active", - "revoked" - ], + "required": ["active", "revoked"], "additionalProperties": false }, "type": { @@ -10130,10 +9103,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "create": { @@ -10193,11 +9163,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "salesChannels": { @@ -10225,9 +9191,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -10251,10 +9215,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "revoke": { @@ -10267,10 +9228,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "addSalesChannels": { @@ -10283,15 +9241,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "removeSalesChannel": { @@ -10339,11 +9293,7 @@ "type": "string" } }, - "required": [ - "revoke", - "copy", - "copySuccessToast" - ], + "required": ["revoke", "copy", "copySuccessToast"], "additionalProperties": false }, "table": { @@ -10356,10 +9306,7 @@ "type": "string" } }, - "required": [ - "lastUsedAtHeader", - "createdAtHeader" - ], + "required": ["lastUsedAtHeader", "createdAtHeader"], "additionalProperties": false }, "fields": { @@ -10436,12 +9383,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "hint", - "successToast" - ], + "required": ["header", "subtitle", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10457,11 +9399,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -10474,10 +9412,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -10496,11 +9431,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder", - "tooltip" - ], + "required": ["label", "placeholder", "tooltip"], "additionalProperties": false }, "label": { @@ -10513,10 +9444,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false }, "description": { @@ -10529,18 +9457,11 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false } }, - "required": [ - "value", - "label", - "description" - ], + "required": ["value", "label", "description"], "additionalProperties": false } }, @@ -10569,11 +9490,7 @@ "type": "string" } }, - "required": [ - "forgotPassword", - "title", - "hint" - ], + "required": ["forgotPassword", "title", "hint"], "additionalProperties": false }, "invite": { @@ -10625,9 +9542,7 @@ "type": "string" } }, - "required": [ - "accepted" - ], + "required": ["accepted"], "additionalProperties": false } }, @@ -10772,9 +9687,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "history": { @@ -10871,15 +9784,11 @@ "type": "string" } }, - "required": [ - "waitingToCompensate" - ], + "required": ["waitingToCompensate"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false }, "step": { @@ -10901,18 +9810,11 @@ "type": "string" } }, - "required": [ - "skipped", - "skippedFailure", - "dormant", - "timeout" - ], + "required": ["skipped", "skippedFailure", "dormant", "timeout"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false } }, @@ -10954,11 +9856,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10971,10 +9869,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -10987,10 +9882,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -11000,20 +9892,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], "additionalProperties": false }, "productTags": { @@ -11035,11 +9918,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "edit": { @@ -11055,11 +9934,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -11072,10 +9947,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -11085,19 +9957,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "create", "edit", "delete", "fields"], "additionalProperties": false }, "notifications": { @@ -11116,10 +9980,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "accessibility": { @@ -11129,17 +9990,11 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false } }, - "required": [ - "domain", - "emptyState", - "accessibility" - ], + "required": ["domain", "emptyState", "accessibility"], "additionalProperties": false }, "errors": { @@ -11152,10 +10007,7 @@ "type": "string" } }, - "required": [ - "serverError", - "invalidCredentials" - ], + "required": ["serverError", "invalidCredentials"], "additionalProperties": false }, "statuses": { @@ -11170,6 +10022,12 @@ "active": { "type": "string" }, + "draft": { + "type": "string" + }, + "inactive": { + "type": "string" + }, "enabled": { "type": "string" }, @@ -11177,13 +10035,7 @@ "type": "string" } }, - "required": [ - "scheduled", - "expired", - "active", - "enabled", - "disabled" - ], + "required": ["draft", "inactive", "active", "scheduled", "expired"], "additionalProperties": false }, "labels": { @@ -11978,4 +10830,4 @@ "dateTime" ], "additionalProperties": false -} \ No newline at end of file +} diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index f4192da83f..fecc64d12f 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -1933,7 +1933,19 @@ } }, "status": { - "title": "Status" + "label": "Status", + "draft": { + "title": "Draft", + "description": "Customers will not be able to use the code yet" + }, + "active": { + "title": "Active", + "description": "Customers will be able to use the code" + }, + "inactive": { + "title": "Inactive", + "description": "Customers will no longer be able to use the code" + } }, "method": { "label": "Method", @@ -2676,6 +2688,8 @@ "scheduled": "Scheduled", "expired": "Expired", "active": "Active", + "inactive": "Inactive", + "draft": "Draft", "enabled": "Enabled", "disabled": "Disabled" }, diff --git a/packages/admin/dashboard/src/lib/promotions.ts b/packages/admin/dashboard/src/lib/promotions.ts index e13d1db445..a2cdc916ae 100644 --- a/packages/admin/dashboard/src/lib/promotions.ts +++ b/packages/admin/dashboard/src/lib/promotions.ts @@ -1,10 +1,28 @@ import { HttpTypes } from "@medusajs/types" +import { i18n } from "../components/utilities/i18n" export enum PromotionStatus { SCHEDULED = "SCHEDULED", EXPIRED = "EXPIRED", ACTIVE = "ACTIVE", - DISABLED = "DISABLED", + INACTIVE = "INACTIVE", + DRAFT = "DRAFT", +} + +export type StatusColors = "grey" | "orange" | "green" | "red" | "grey" +export type StatusMap = Record +export const promotionStatusMap: StatusMap = { + [PromotionStatus.ACTIVE]: ["green", i18n.t("statuses.active")], + [PromotionStatus.INACTIVE]: ["red", i18n.t("statuses.inactive")], + [PromotionStatus.DRAFT]: ["grey", i18n.t("statuses.draft")], + [PromotionStatus.SCHEDULED]: [ + "orange", + `${i18n.t("promotions.fields.campaign")} ${i18n.t("statuses.scheduled").toLowerCase()}`, + ], + [PromotionStatus.EXPIRED]: [ + "red", + `${i18n.t("promotions.fields.campaign")} ${i18n.t("statuses.expired").toLowerCase()}`, + ], } export const getPromotionStatus = (promotion: HttpTypes.AdminPromotion) => { @@ -12,11 +30,11 @@ export const getPromotionStatus = (promotion: HttpTypes.AdminPromotion) => { const campaign = promotion.campaign if (!campaign) { - return PromotionStatus.ACTIVE + return promotionStatusMap[promotion.status!.toUpperCase()] } - if (new Date(campaign.starts_at!) > date) { - return PromotionStatus.SCHEDULED + if (campaign.starts_at && new Date(campaign.starts_at!) > date) { + return promotionStatusMap[PromotionStatus.SCHEDULED] } const campaignBudget = campaign.budget @@ -24,8 +42,8 @@ export const getPromotionStatus = (promotion: HttpTypes.AdminPromotion) => { campaignBudget && campaignBudget.used! > campaignBudget.limit! if ((campaign.ends_at && new Date(campaign.ends_at) < date) || overBudget) { - return PromotionStatus.EXPIRED + return promotionStatusMap[PromotionStatus.EXPIRED] } - return PromotionStatus.ACTIVE + return promotionStatusMap[promotion.status!.toUpperCase()] } diff --git a/packages/admin/dashboard/src/routes/promotions/promotion-create/components/create-promotion-form/create-promotion-form.tsx b/packages/admin/dashboard/src/routes/promotions/promotion-create/components/create-promotion-form/create-promotion-form.tsx index 47c01ae51b..7d3214bf79 100644 --- a/packages/admin/dashboard/src/routes/promotions/promotion-create/components/create-promotion-form/create-promotion-form.tsx +++ b/packages/admin/dashboard/src/routes/promotions/promotion-create/components/create-promotion-form/create-promotion-form.tsx @@ -1,4 +1,12 @@ import { zodResolver } from "@hookform/resolvers/zod" +import { + ApplicationMethodAllocationValues, + ApplicationMethodTargetTypeValues, + ApplicationMethodTypeValues, + PromotionRuleOperatorValues, + PromotionStatusValues, + PromotionTypeValues, +} from "@medusajs/types" import { Alert, Badge, @@ -17,14 +25,6 @@ import { useEffect, useMemo, useState } from "react" import { useForm, useWatch } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { z } from "zod" - -import { - ApplicationMethodAllocationValues, - ApplicationMethodTargetTypeValues, - ApplicationMethodTypeValues, - PromotionRuleOperatorValues, - PromotionTypeValues, -} from "@medusajs/types" import { Divider } from "../../../../../components/common/divider" import { Form } from "../../../../../components/common/form" import { DeprecatedPercentageInput } from "../../../../../components/inputs/percentage-input" @@ -50,6 +50,7 @@ const defaultValues = { is_automatic: "false", code: "", type: "standard" as PromotionTypeValues, + status: "draft" as PromotionStatusValues, rules: [], application_method: { allocation: "each" as ApplicationMethodAllocationValues, @@ -508,6 +509,48 @@ export const CreatePromotionForm = () => { }} /> + { + return ( + + + {t("promotions.form.status.label")} + + + + + + + + + + + + ) + }} + /> +
+ { + return ( + + {t("promotions.form.status.label")} + + + + + + + + + + + + ) + }} + /> + { + updatePromotionsValidationStep(input) + + const updatedPromotions = updatePromotionsStep(input.promotionsData) + + const promotionStatusUpdated = createHook("promotionStatusUpdated", { + promotions: updatedPromotions, + additional_data: input.additional_data, + }) + + return new WorkflowResponse(updatedPromotions, { + hooks: [promotionStatusUpdated], + }) + } +) diff --git a/packages/core/core-flows/src/promotion/workflows/update-promotions.ts b/packages/core/core-flows/src/promotion/workflows/update-promotions.ts index aec633c826..7c87aad48f 100644 --- a/packages/core/core-flows/src/promotion/workflows/update-promotions.ts +++ b/packages/core/core-flows/src/promotion/workflows/update-promotions.ts @@ -1,11 +1,21 @@ -import { AdditionalData, UpdatePromotionDTO } from "@medusajs/framework/types" import { - WorkflowData, - WorkflowResponse, + AdditionalData, + PromotionDTO, + PromotionStatusValues, + UpdatePromotionDTO, +} from "@medusajs/framework/types" +import { isString } from "@medusajs/framework/utils" +import { createHook, createWorkflow, + transform, + when, + WorkflowData, + WorkflowResponse, } from "@medusajs/framework/workflows-sdk" +import { useRemoteQueryStep } from "../../common" import { updatePromotionsStep } from "../steps" +import { updatePromotionsStatusWorkflow } from "./update-promotions-status" /** * The data to update one or more promotions, along with custom data that's passed to the workflow's hooks. @@ -20,12 +30,12 @@ export type UpdatePromotionsWorkflowInput = { export const updatePromotionsWorkflowId = "update-promotions" /** * This workflow updates one or more promotions. It's used by the [Update Promotion Admin API Route](https://docs.medusajs.com/api/admin#promotions_postpromotionsid). - * + * * This workflow has a hook that allows you to perform custom actions on the updated promotion. For example, you can pass under `additional_data` custom data that * allows you to update custom data models linked to the promotions. - * + * * You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around updating promotions. - * + * * @example * const { result } = await updatePromotionsWorkflow(container) * .run({ @@ -41,17 +51,78 @@ export const updatePromotionsWorkflowId = "update-promotions" * } * } * }) - * + * * @summary - * + * * Update one or more promotions. - * + * * @property hooks.promotionsUpdated - This hook is executed after the promotions are updated. You can consume this hook to perform custom actions on the updated promotions. */ export const updatePromotionsWorkflow = createWorkflow( updatePromotionsWorkflowId, (input: WorkflowData) => { - const updatedPromotions = updatePromotionsStep(input.promotionsData) + const promotionIds = transform({ input }, ({ input }) => + input.promotionsData.map((pd) => pd.id) + ) + + const promotions = useRemoteQueryStep({ + entry_point: "promotion", + variables: { id: promotionIds }, + fields: ["id", "status"], + list: true, + throw_if_key_not_found: true, + }).config({ name: "get-promotions" }) + + const promotionInputs = transform( + { promotions, input }, + ({ promotions, input }) => { + const promotionMap: Record = {} + const promotionsUpdateInput: UpdatePromotionsWorkflowInput["promotionsData"] = + [] + const promotionsStatusUpdateInput: { + id: string + status: PromotionStatusValues + }[] = [] + + for (const promotion of promotions) { + promotionMap[promotion.id] = promotion + } + + for (const promotionUpdateData of input.promotionsData) { + const promotion = promotionMap[promotionUpdateData.id] + const { status, ...rest } = promotionUpdateData + + promotionsUpdateInput.push(rest) + + if ( + isString(status) && + promotionUpdateData.status !== promotion.status + ) { + promotionsStatusUpdateInput.push({ + id: promotionUpdateData.id, + status, + }) + } + } + + return { promotionsUpdateInput, promotionsStatusUpdateInput } + } + ) + + const updatedPromotions = updatePromotionsStep( + promotionInputs.promotionsUpdateInput + ) + + when({ promotionInputs }, ({ promotionInputs }) => { + return !!promotionInputs.promotionsStatusUpdateInput?.length + }).then(() => { + updatePromotionsStatusWorkflow.runAsStep({ + input: { + promotionsData: promotionInputs.promotionsStatusUpdateInput, + }, + }) + }) + const promotionsUpdated = createHook("promotionsUpdated", { promotions: updatedPromotions, additional_data: input.additional_data, diff --git a/packages/core/types/src/http/promotion/admin/payloads.ts b/packages/core/types/src/http/promotion/admin/payloads.ts index 3d44807bee..cdf79f744a 100644 --- a/packages/core/types/src/http/promotion/admin/payloads.ts +++ b/packages/core/types/src/http/promotion/admin/payloads.ts @@ -3,6 +3,7 @@ import { ApplicationMethodTargetTypeValues, ApplicationMethodTypeValues, PromotionRuleOperatorValues, + PromotionStatusValues, PromotionTypeValues, } from "../../../promotion" import { AdminCreateCampaign } from "../../campaign" @@ -64,6 +65,7 @@ export interface AdminUpdatePromotion { code?: string is_automatic?: boolean type?: PromotionTypeValues + status?: PromotionStatusValues campaign_id?: string | null campaign?: AdminCreateCampaign application_method?: AdminUpdateApplicationMethod diff --git a/packages/core/types/src/http/promotion/common.ts b/packages/core/types/src/http/promotion/common.ts index 258bfaef12..8b406960eb 100644 --- a/packages/core/types/src/http/promotion/common.ts +++ b/packages/core/types/src/http/promotion/common.ts @@ -3,6 +3,7 @@ import { ApplicationMethodTargetTypeValues, ApplicationMethodTypeValues, PromotionRuleOperatorValues, + PromotionStatusValues, PromotionTypeValues, } from "../../promotion" import { AdminCampaign } from "../campaign" @@ -37,6 +38,7 @@ export interface BasePromotion { is_automatic?: boolean application_method?: BaseApplicationMethod rules?: BasePromotionRule[] + status?: PromotionStatusValues campaign_id?: string campaign?: AdminCampaign created_at: string diff --git a/packages/core/types/src/promotion/common/promotion.ts b/packages/core/types/src/promotion/common/promotion.ts index dad6290d61..32c5c9523c 100644 --- a/packages/core/types/src/promotion/common/promotion.ts +++ b/packages/core/types/src/promotion/common/promotion.ts @@ -5,7 +5,7 @@ import { CreateApplicationMethodDTO, UpdateApplicationMethodDTO, } from "./application-method" -import { CampaignDTO } from "./campaign" +import { CampaignDTO, FilterableCampaignProps } from "./campaign" import { CreatePromotionRuleDTO, PromotionRuleDTO } from "./promotion-rule" /** @@ -13,6 +13,11 @@ import { CreatePromotionRuleDTO, PromotionRuleDTO } from "./promotion-rule" */ export type PromotionTypeValues = "standard" | "buyget" +/** + * The promotion's possible types. + */ +export type PromotionStatusValues = "draft" | "active" | "inactive" + /** * The promotion's possible rule types. */ @@ -41,6 +46,15 @@ export interface PromotionDTO { */ type?: PromotionTypeValues + /** + * The status of the promotion: + * + * - `active` promotion is available for user to consume + * - `inactive` promotion is no longer available to the user + * - `draft` promotion is currently being prepared + */ + status?: PromotionStatusValues + /** * Whether the promotion is applied automatically. */ @@ -85,6 +99,15 @@ export interface CreatePromotionDTO { */ type: PromotionTypeValues + /** + * The status of the promotion: + * + * - `draft` indicates that a promotion is currently being prepared + * - `active` indicates that a promotion is active + * - `inactive` indicates that a promotion is no longer active + */ + status: PromotionStatusValues + /** * Whether the promotion is applied automatically. */ @@ -135,6 +158,15 @@ export interface UpdatePromotionDTO { */ type?: PromotionTypeValues + /** + * The status of the promotion: + * + * - `draft` indicates that a promotion is currently being prepared + * - `active` indicates that a promotion is active + * - `inactive` indicates that a promotion is no longer active + */ + status?: PromotionStatusValues + /** * The associated application method. */ @@ -180,4 +212,14 @@ export interface FilterablePromotionProps * Filter promotions by their type. */ type?: PromotionTypeValues[] + + /** + * Filter promotions by their status. + */ + status?: PromotionStatusValues[] + + /** + * Filter promotions by their campaign + */ + campaign?: FilterableCampaignProps } diff --git a/packages/core/utils/src/promotion/index.ts b/packages/core/utils/src/promotion/index.ts index cd55398b36..5dd3a497f9 100644 --- a/packages/core/utils/src/promotion/index.ts +++ b/packages/core/utils/src/promotion/index.ts @@ -3,6 +3,12 @@ export enum PromotionType { BUYGET = "buyget", } +export enum PromotionStatus { + DRAFT = "draft", + ACTIVE = "active", + INACTIVE = "inactive", +} + export enum ApplicationMethodType { FIXED = "fixed", PERCENTAGE = "percentage", diff --git a/packages/medusa/src/api/admin/promotions/query-config.ts b/packages/medusa/src/api/admin/promotions/query-config.ts index d39536ed68..babd23b3cc 100644 --- a/packages/medusa/src/api/admin/promotions/query-config.ts +++ b/packages/medusa/src/api/admin/promotions/query-config.ts @@ -3,6 +3,7 @@ export const defaultAdminPromotionFields = [ "code", "is_automatic", "type", + "status", "created_at", "updated_at", "deleted_at", diff --git a/packages/medusa/src/api/admin/promotions/validators.ts b/packages/medusa/src/api/admin/promotions/validators.ts index f014d4d7b1..09067929db 100644 --- a/packages/medusa/src/api/admin/promotions/validators.ts +++ b/packages/medusa/src/api/admin/promotions/validators.ts @@ -3,9 +3,11 @@ import { ApplicationMethodTargetType, ApplicationMethodType, PromotionRuleOperator, + PromotionStatus, PromotionType, } from "@medusajs/framework/utils" import { z } from "zod" +import { applyAndAndOrOperators } from "../../utils/common-validators" import { createFindParams, createOperatorMap, @@ -13,7 +15,6 @@ import { WithAdditionalData, } from "../../utils/validators" import { CreateCampaign } from "../campaigns/validators" -import { applyAndAndOrOperators } from "../../utils/common-validators" export type AdminGetPromotionParamsType = z.infer< typeof AdminGetPromotionParams @@ -160,6 +161,7 @@ export const CreatePromotion = z code: z.string(), is_automatic: z.boolean().optional(), type: z.nativeEnum(PromotionType), + status: z.nativeEnum(PromotionStatus).default(PromotionStatus.DRAFT), campaign_id: z.string().nullish(), campaign: CreateCampaign.optional(), application_method: AdminCreateApplicationMethod, @@ -183,6 +185,7 @@ export const UpdatePromotion = z code: z.string().optional(), is_automatic: z.boolean().optional(), type: z.nativeEnum(PromotionType).optional(), + status: z.nativeEnum(PromotionStatus).optional(), campaign_id: z.string().nullish(), application_method: AdminUpdateApplicationMethod.optional(), }) diff --git a/packages/modules/promotion/integration-tests/__fixtures__/promotion/index.ts b/packages/modules/promotion/integration-tests/__fixtures__/promotion/index.ts index ee616dfb6f..66b8a80545 100644 --- a/packages/modules/promotion/integration-tests/__fixtures__/promotion/index.ts +++ b/packages/modules/promotion/integration-tests/__fixtures__/promotion/index.ts @@ -3,7 +3,11 @@ import { IPromotionModuleService, PromotionDTO, } from "@medusajs/framework/types" -import { isPresent, toMikroORMEntity } from "@medusajs/framework/utils" +import { + isPresent, + PromotionStatus, + toMikroORMEntity, +} from "@medusajs/framework/utils" import { SqlEntityManager } from "@mikro-orm/postgresql" import { Promotion } from "@models" import { defaultPromotionsData } from "./data" @@ -51,6 +55,7 @@ export async function createDefaultPromotion( return await service.createPromotions({ code: "PROMOTION_TEST", type: "standard", + status: PromotionStatus.ACTIVE, campaign_id: "campaign-id-1", ...promotion, application_method: { diff --git a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/compute-actions.spec.ts b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/compute-actions.spec.ts index 0e50bf8712..b920fd674e 100644 --- a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/compute-actions.spec.ts +++ b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/compute-actions.spec.ts @@ -2,6 +2,7 @@ import { IPromotionModuleService } from "@medusajs/framework/types" import { ApplicationMethodType, Modules, + PromotionStatus, PromotionType, } from "@medusajs/framework/utils" import { moduleIntegrationTestRunner, SuiteOptions } from "@medusajs/test-utils" @@ -17,13 +18,85 @@ moduleIntegrationTestRunner({ service, }: SuiteOptions) => { describe("Promotion Service: computeActions", () => { + beforeAll(() => { + jest.useFakeTimers() + jest.setSystemTime(new Date("02/02/2023")) + }) + + afterAll(() => { + jest.useRealTimers() + }) + beforeEach(async () => { await createCampaigns(MikroOrmWrapper.forkManager()) }) + it("should return empty array when promotion is not active (draft or inactive)", async () => { + const promotion = await createDefaultPromotion(service, { + status: PromotionStatus.DRAFT, + rules: [ + { + attribute: "customer.customer_group.id", + operator: "in", + values: ["VIP", "top100"], + }, + ], + application_method: { + type: "fixed", + target_type: "items", + allocation: "each", + value: 200, + max_quantity: 1, + target_rules: [ + { + attribute: "product_category.id", + operator: "eq", + values: ["catg_cotton"], + }, + ], + }, + }) + + const result = await service.computeActions([promotion.code!], { + currency_code: "usd", + customer: { + customer_group: { + id: "VIP", + }, + }, + items: [ + { + id: "item_cotton_tshirt", + quantity: 1, + subtotal: 100, + product_category: { + id: "catg_cotton", + }, + product: { + id: "prod_tshirt", + }, + }, + { + id: "item_cotton_sweater", + quantity: 5, + subtotal: 750, + product_category: { + id: "catg_cotton", + }, + product: { + id: "prod_sweater", + }, + }, + ], + }) + + expect(result).toEqual([]) + }) + describe("when code is not present in database", () => { it("should return empty array when promotion does not exist", async () => { const response = await service.computeActions(["DOES_NOT_EXIST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -87,6 +160,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -136,6 +210,7 @@ moduleIntegrationTestRunner({ const resultWithoutCustomer = await service.computeActions( ["PROMOTION_TEST"], { + currency_code: "usd", items: [ { id: "item_cotton_tshirt", @@ -221,6 +296,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -257,19 +333,7 @@ moduleIntegrationTestRunner({ { action: "addItemAdjustment", item_id: "item_cotton_tshirt", - amount: 30, - code: "PROMOTION_TEST", - }, - { - action: "addItemAdjustment", - item_id: "item_cotton_sweater", - amount: 30, - code: "PROMOTION_TEST", - }, - { - action: "addItemAdjustment", - item_id: "item_cotton_tshirt", - amount: 20, + amount: 50, code: "PROMOTION_TEST_2", }, { @@ -278,6 +342,12 @@ moduleIntegrationTestRunner({ amount: 50, code: "PROMOTION_TEST_2", }, + { + action: "addItemAdjustment", + item_id: "item_cotton_sweater", + amount: 30, + code: "PROMOTION_TEST", + }, ]) }) @@ -334,6 +404,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -408,6 +479,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -469,6 +541,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -522,6 +595,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -622,6 +696,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -735,6 +810,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -809,6 +885,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -866,6 +943,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -921,6 +999,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -994,6 +1073,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions([], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1093,6 +1173,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1126,18 +1207,6 @@ moduleIntegrationTestRunner({ ) expect(JSON.parse(JSON.stringify(result))).toEqual([ - { - action: "addItemAdjustment", - item_id: "item_cotton_tshirt", - amount: 7.5, - code: "PROMOTION_TEST", - }, - { - action: "addItemAdjustment", - item_id: "item_cotton_sweater", - amount: 22.5, - code: "PROMOTION_TEST", - }, { action: "addItemAdjustment", item_id: "item_cotton_tshirt", @@ -1150,6 +1219,18 @@ moduleIntegrationTestRunner({ amount: 37.5, code: "PROMOTION_TEST_2", }, + { + action: "addItemAdjustment", + item_id: "item_cotton_tshirt", + amount: 7.5, + code: "PROMOTION_TEST", + }, + { + action: "addItemAdjustment", + item_id: "item_cotton_sweater", + amount: 22.5, + code: "PROMOTION_TEST", + }, ]) }) @@ -1205,6 +1286,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1278,6 +1360,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1334,6 +1417,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1386,6 +1470,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1459,6 +1544,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions([], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1557,6 +1643,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1668,6 +1755,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1753,6 +1841,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1809,6 +1898,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1864,6 +1954,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -1937,6 +2028,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions([], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -2012,6 +2104,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( [], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -2100,6 +2193,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -2206,6 +2300,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -2279,6 +2374,7 @@ moduleIntegrationTestRunner({ }) const result = await service.computeActions(["PROMOTION_TEST"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -3974,6 +4070,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", @@ -4007,18 +4104,6 @@ moduleIntegrationTestRunner({ ) expect(JSON.parse(JSON.stringify(result))).toEqual([ - { - action: "addItemAdjustment", - item_id: "item_cotton_tshirt", - amount: 7.5, - code: "PROMOTION_TEST", - }, - { - action: "addItemAdjustment", - item_id: "item_cotton_sweater", - amount: 22.5, - code: "PROMOTION_TEST", - }, { action: "addItemAdjustment", item_id: "item_cotton_tshirt", @@ -4031,6 +4116,18 @@ moduleIntegrationTestRunner({ amount: 37.5, code: "PROMOTION_TEST_2", }, + { + action: "addItemAdjustment", + item_id: "item_cotton_tshirt", + amount: 7.5, + code: "PROMOTION_TEST", + }, + { + action: "addItemAdjustment", + item_id: "item_cotton_sweater", + amount: 22.5, + code: "PROMOTION_TEST", + }, ]) }) @@ -4073,6 +4170,7 @@ moduleIntegrationTestRunner({ const result = await service.computeActions( ["PROMOTION_TEST", "PROMOTION_TEST_2"], { + currency_code: "usd", customer: { customer_group: { id: "VIP", diff --git a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts index 8cc7b9b54d..60ab7830dc 100644 --- a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts +++ b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/promotion.spec.ts @@ -6,8 +6,8 @@ import { Modules, PromotionType, } from "@medusajs/framework/utils" -import { PromotionModuleService } from "@services" import { SuiteOptions, moduleIntegrationTestRunner } from "@medusajs/test-utils" +import { PromotionModuleService } from "@services" import { createCampaigns } from "../../../__fixtures__/campaigns" import { createDefaultPromotion, @@ -24,6 +24,15 @@ moduleIntegrationTestRunner({ service, }: SuiteOptions) => { describe("Promotion Service", () => { + beforeAll(() => { + jest.useFakeTimers() + jest.setSystemTime(new Date("02/02/2023")) + }) + + afterAll(() => { + jest.useRealTimers() + }) + beforeEach(async () => { await createCampaigns(MikroOrmWrapper.forkManager()) }) @@ -809,30 +818,32 @@ moduleIntegrationTestRunner({ expect(count).toEqual(2) expect(promotions).toEqual([ - { + expect.objectContaining({ id: "promotion-id-1", code: "PROMOTION_1", campaign_id: null, campaign: null, + status: "draft", is_automatic: false, type: "standard", application_method: expect.any(Object), created_at: expect.any(Date), updated_at: expect.any(Date), deleted_at: null, - }, - { + }), + expect.objectContaining({ id: "promotion-id-2", code: "PROMOTION_2", campaign_id: null, campaign: null, + status: "draft", is_automatic: false, type: "standard", application_method: null, created_at: expect.any(Date), updated_at: expect.any(Date), deleted_at: null, - }, + }), ]) }) diff --git a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/register-usage.spec.ts b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/register-usage.spec.ts index 2e2731e3bd..278a97986f 100644 --- a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/register-usage.spec.ts +++ b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/register-usage.spec.ts @@ -1,8 +1,8 @@ import { IPromotionModuleService } from "@medusajs/framework/types" +import { Modules } from "@medusajs/framework/utils" import { moduleIntegrationTestRunner, SuiteOptions } from "@medusajs/test-utils" import { createCampaigns } from "../../../__fixtures__/campaigns" import { createDefaultPromotion } from "../../../__fixtures__/promotion" -import { Modules } from "@medusajs/framework/utils" jest.setTimeout(30000) @@ -13,6 +13,15 @@ moduleIntegrationTestRunner({ service, }: SuiteOptions) => { describe("Promotion Service: campaign usage", () => { + beforeAll(() => { + jest.useFakeTimers() + jest.setSystemTime(new Date("02/02/2023")) + }) + + afterAll(() => { + jest.useRealTimers() + }) + beforeEach(async () => { await createCampaigns(MikroOrmWrapper.forkManager()) }) diff --git a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/revert-usage.spec.ts b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/revert-usage.spec.ts index f848d30297..abd5f86777 100644 --- a/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/revert-usage.spec.ts +++ b/packages/modules/promotion/integration-tests/__tests__/services/promotion-module/revert-usage.spec.ts @@ -13,6 +13,15 @@ moduleIntegrationTestRunner({ service, }: SuiteOptions) => { describe("Promotion Service: campaign usage", () => { + beforeAll(() => { + jest.useFakeTimers() + jest.setSystemTime(new Date("02/02/2023")) + }) + + afterAll(() => { + jest.useRealTimers() + }) + beforeEach(async () => { await createCampaigns(MikroOrmWrapper.forkManager()) }) diff --git a/packages/modules/promotion/src/migrations/.snapshot-medusa-promotion.json b/packages/modules/promotion/src/migrations/.snapshot-medusa-promotion.json index 7f8d1ea64e..406f1c5108 100644 --- a/packages/modules/promotion/src/migrations/.snapshot-medusa-promotion.json +++ b/packages/modules/promotion/src/migrations/.snapshot-medusa-promotion.json @@ -345,6 +345,21 @@ ], "mappedType": "enum" }, + "status": { + "name": "status", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "'draft'", + "enumItems": [ + "draft", + "active", + "inactive" + ], + "mappedType": "enum" + }, "campaign_id": { "name": "campaign_id", "type": "text", @@ -414,6 +429,14 @@ "unique": false, "expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_type\" ON \"promotion\" (type) WHERE deleted_at IS NULL" }, + { + "keyName": "IDX_promotion_status", + "columnNames": [], + "composite": false, + "primary": false, + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_promotion_status\" ON \"promotion\" (status) WHERE deleted_at IS NULL" + }, { "keyName": "IDX_promotion_campaign_id", "columnNames": [], diff --git a/packages/modules/promotion/src/migrations/Migration20250113094144.ts b/packages/modules/promotion/src/migrations/Migration20250113094144.ts new file mode 100644 index 0000000000..69f8e14584 --- /dev/null +++ b/packages/modules/promotion/src/migrations/Migration20250113094144.ts @@ -0,0 +1,23 @@ +import { Migration } from "@mikro-orm/migrations" + +export class Migration20250113094144 extends Migration { + async up(): Promise { + this.addSql( + "alter table if exists \"promotion\" add column if not exists \"status\" text check (\"status\" in ('draft', 'active', 'inactive')) not null default 'draft';" + ) + + this.addSql( + 'CREATE INDEX IF NOT EXISTS "IDX_promotion_status" ON "promotion" (status) WHERE deleted_at IS NULL;' + ) + + // Data Migration + this.addSql(`UPDATE promotion SET status = 'active';`) + } + + async down(): Promise { + this.addSql('drop index if exists "IDX_promotion_status";') + this.addSql( + 'alter table if exists "promotion" drop column if exists "status";' + ) + } +} diff --git a/packages/modules/promotion/src/models/promotion.ts b/packages/modules/promotion/src/models/promotion.ts index 56c57a4acf..ff10fc3151 100644 --- a/packages/modules/promotion/src/models/promotion.ts +++ b/packages/modules/promotion/src/models/promotion.ts @@ -13,6 +13,10 @@ const Promotion = model .index("IDX_promotion_code"), is_automatic: model.boolean().default(false), type: model.enum(PromotionUtils.PromotionType).index("IDX_promotion_type"), + status: model + .enum(PromotionUtils.PromotionStatus) + .index("IDX_promotion_status") + .default(PromotionUtils.PromotionStatus.DRAFT), campaign: model .belongsTo(() => Campaign, { mappedBy: "promotions", diff --git a/packages/modules/promotion/src/services/promotion-module.ts b/packages/modules/promotion/src/services/promotion-module.ts index 96cd6c2117..3ff1b79250 100644 --- a/packages/modules/promotion/src/services/promotion-module.ts +++ b/packages/modules/promotion/src/services/promotion-module.ts @@ -2,10 +2,13 @@ import { CampaignBudgetTypeValues, Context, DAL, + FilterablePromotionProps, + FindConfig, InferEntityType, InternalModuleDeclaration, ModuleJoinerConfig, ModulesSdkTypes, + PromotionDTO, PromotionTypes, } from "@medusajs/framework/types" import { @@ -24,6 +27,7 @@ import { MedusaContext, MedusaError, MedusaService, + PromotionStatus, PromotionType, toMikroORMEntity, transformPropertiesToBigNumber, @@ -134,6 +138,40 @@ export default class PromotionModuleService return joinerConfig } + @InjectManager() + listActivePromotions( + filters?: FilterablePromotionProps, + config?: FindConfig, + sharedContext?: Context + ): Promise { + const activeFilters = { + $or: [ + { + status: PromotionStatus.ACTIVE, + campaign_id: null, + ...filters, + }, + { + status: PromotionStatus.ACTIVE, + ...filters, + campaign: { + ...filters?.campaign, + $and: [ + { + $or: [{ starts_at: null }, { starts_at: { $lte: new Date() } }], + }, + { + $or: [{ ends_at: null }, { ends_at: { $gt: new Date() } }], + }, + ], + }, + }, + ], + } + + return this.listPromotions(activeFilters, config, sharedContext) + } + @InjectManager() async registerUsage( computedActions: PromotionTypes.UsageComputedActions[], @@ -148,11 +186,9 @@ export default class PromotionModuleService const campaignBudgetMap = new Map() const promotionCodeUsageMap = new Map() - const existingPromotions = await this.listPromotions( + const existingPromotions = await this.listActivePromotions( { code: promotionCodes }, - { - relations: ["campaign", "campaign.budget"], - }, + { relations: ["campaign", "campaign.budget"] }, sharedContext ) @@ -250,15 +286,13 @@ export default class PromotionModuleService const promotionCodeUsageMap = new Map() const campaignBudgetMap = new Map() - const existingPromotions = await this.listPromotions( + const existingPromotions = await this.listActivePromotions( { code: computedActions .map((computedAction) => computedAction.code) .filter(Boolean), }, - { - relations: ["campaign", "campaign.budget"], - }, + { relations: ["campaign", "campaign.budget"] }, sharedContext ) @@ -362,7 +396,7 @@ export default class PromotionModuleService >() const automaticPromotions = preventAutoPromotions ? [] - : await this.listPromotions( + : await this.listActivePromotions( { is_automatic: true }, { select: ["code"] }, sharedContext @@ -402,7 +436,7 @@ export default class PromotionModuleService }) }) - const promotions = await this.listPromotions( + const promotions = await this.listActivePromotions( { code: [ ...promotionCodesToApply, @@ -412,6 +446,7 @@ export default class PromotionModuleService }, { take: null, + order: { application_method: { value: "DESC" } }, relations: [ "application_method", "application_method.target_rules",