diff --git a/.changeset/angry-ghosts-taste.md b/.changeset/angry-ghosts-taste.md new file mode 100644 index 0000000000000..40700194778ab --- /dev/null +++ b/.changeset/angry-ghosts-taste.md @@ -0,0 +1,7 @@ +--- +"@medusajs/workflows": patch +"@medusajs/pricing": patch +"@medusajs/medusa": patch +--- + +fix(workflows, pricing, medusa): update region variants fix + pricing module migration scripts diff --git a/.changeset/breezy-readers-shout.md b/.changeset/breezy-readers-shout.md new file mode 100644 index 0000000000000..d22d66c39cc63 --- /dev/null +++ b/.changeset/breezy-readers-shout.md @@ -0,0 +1,7 @@ +--- +"@medusajs/workflows": patch +"@medusajs/product": patch +"@medusajs/types": patch +--- + +fix(workflows, product, types): Fix issues relating to update-variant workflow and options diff --git a/.changeset/khaki-eyes-fetch.md b/.changeset/khaki-eyes-fetch.md new file mode 100644 index 0000000000000..5c20b29f3256f --- /dev/null +++ b/.changeset/khaki-eyes-fetch.md @@ -0,0 +1,5 @@ +--- +"@medusajs/admin-ui": patch +--- + +fix(admin-ui): delete edit variant prices in favor of bulk editor diff --git a/.changeset/kind-dolphins-speak.md b/.changeset/kind-dolphins-speak.md new file mode 100644 index 0000000000000..0b3b53f44e004 --- /dev/null +++ b/.changeset/kind-dolphins-speak.md @@ -0,0 +1,6 @@ +--- +"@medusajs/pricing": patch +"@medusajs/types": patch +--- + +fix(pricing,types): remove is_dynamic from model + types diff --git a/.changeset/small-apes-own.md b/.changeset/small-apes-own.md new file mode 100644 index 0000000000000..38fbbbbe16b2a --- /dev/null +++ b/.changeset/small-apes-own.md @@ -0,0 +1,5 @@ +--- +"@medusajs/workflows": patch +--- + +Fix(workflows): compensation handling diff --git a/.changeset/wet-crews-sneeze.md b/.changeset/wet-crews-sneeze.md new file mode 100644 index 0000000000000..fb5151f9131f7 --- /dev/null +++ b/.changeset/wet-crews-sneeze.md @@ -0,0 +1,8 @@ +--- +"@medusajs/orchestration": minor +"@medusajs/workflows": minor +"@medusajs/link-modules": patch +"@medusajs/medusa": patch +--- + +Workflows composer api diff --git a/.changeset/witty-waves-rhyme.md b/.changeset/witty-waves-rhyme.md new file mode 100644 index 0000000000000..db4889d661784 --- /dev/null +++ b/.changeset/witty-waves-rhyme.md @@ -0,0 +1,5 @@ +--- +"@medusajs/ui": patch +--- + +fix(ui): Update the styling of CodeBlock diff --git a/.changeset/young-items-drop.md b/.changeset/young-items-drop.md new file mode 100644 index 0000000000000..9e522b10a0d01 --- /dev/null +++ b/.changeset/young-items-drop.md @@ -0,0 +1,10 @@ +--- +"@medusajs/workflows": patch +"@medusajs/product": patch +"@medusajs/pricing": patch +"@medusajs/medusa": patch +"@medusajs/types": patch +"@medusajs/utils": patch +--- + +feat(medusa,types,workflows,utils,product,pricing): PricingModule Integration of PriceLists into Core diff --git a/.eslintignore b/.eslintignore index 0469b3263f8bf..dbe62ec0c90a2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -21,6 +21,8 @@ packages/* !packages/cache-inmemory !packages/create-medusa-app !packages/product +!packages/orchestration +!packages/workflows **/models/* diff --git a/.eslintrc.js b/.eslintrc.js index 1f757251da28a..83745e590b6bb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -90,14 +90,14 @@ module.exports = { "./packages/event-bus-redis/tsconfig.spec.json", "./packages/medusa-plugin-meilisearch/tsconfig.spec.json", "./packages/medusa-plugin-algolia/tsconfig.spec.json", - "./packages/admin-ui/tsconfig.json", "./packages/inventory/tsconfig.spec.json", "./packages/stock-location/tsconfig.spec.json", "./packages/cache-redis/tsconfig.spec.json", "./packages/cache-inmemory/tsconfig.spec.json", - "./packages/admin-ui/tsconfig.json", "./packages/create-medusa-app/tsconfig.json", "./packages/product/tsconfig.json", + "./packages/orchestration/tsconfig.json", + "./packages/workflows/tsconfig.spec.json", ], }, rules: { diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 5abe7f362b4cf..ba8afeb43725c 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -125,7 +125,6 @@ jobs: env: DB_PASSWORD: postgres DB_USERNAME: postgres - SPLIT: ${{ steps['split-tests'].outputs['split'] }} integration-tests-api: needs: setup @@ -186,7 +185,8 @@ jobs: run: yarn test:integration:api env: DB_PASSWORD: postgres - SPLIT: ${{ steps['split-tests'].outputs['split'] }} + DB_USERNAME: postgres + integration-tests-plugins: needs: setup @@ -237,6 +237,7 @@ jobs: - name: Run plugin integration tests run: yarn test:integration:plugins env: + DB_USERNAME: postgres DB_PASSWORD: postgres NODE_OPTIONS: "--max_old_space_size=4096" @@ -286,4 +287,5 @@ jobs: - name: Run repository integration tests run: yarn test:integration:repositories env: + DB_USERNAME: postgres DB_PASSWORD: postgres diff --git a/docs-util/packages/typedoc-config/_base.js b/docs-util/packages/typedoc-config/_base.js index ee874baf8355b..aafaa94e69ea3 100644 --- a/docs-util/packages/typedoc-config/_base.js +++ b/docs-util/packages/typedoc-config/_base.js @@ -14,6 +14,7 @@ module.exports = { ), pluginsResolvePath: path.join(pathPrefix, "www"), exclude: [path.join(pathPrefix, "node_modules/**")], + excludeInternal: true, // Uncomment this when debugging // showConfig: true, } diff --git a/docs-util/packages/typedoc-config/extended-tsconfig/tsdoc.json b/docs-util/packages/typedoc-config/extended-tsconfig/tsdoc.json index 06df94198f8a7..e7fc48182354a 100644 --- a/docs-util/packages/typedoc-config/extended-tsconfig/tsdoc.json +++ b/docs-util/packages/typedoc-config/extended-tsconfig/tsdoc.json @@ -17,6 +17,14 @@ { "tagName": "@apiIgnore", "syntaxKind": "modifier" + }, + { + "tagName": "@mainSignature", + "syntaxKind": "modifier" + }, + { + "tagName": "@docHideSignature", + "syntaxKind": "modifier" } ] } \ No newline at end of file diff --git a/docs-util/packages/typedoc-config/extended-tsconfig/workflows.json b/docs-util/packages/typedoc-config/extended-tsconfig/workflows.json new file mode 100644 index 0000000000000..35d3b4171b784 --- /dev/null +++ b/docs-util/packages/typedoc-config/extended-tsconfig/workflows.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": [ + "../../../../packages/workflows/tsconfig.json" + ] +} \ No newline at end of file diff --git a/docs-util/packages/typedoc-config/workflows.js b/docs-util/packages/typedoc-config/workflows.js new file mode 100644 index 0000000000000..199ea0b5dbf7d --- /dev/null +++ b/docs-util/packages/typedoc-config/workflows.js @@ -0,0 +1,75 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const path = require("path") +const globalTypedocOptions = require("./_base") + +const pathPrefix = path.join(__dirname, "..", "..", "..") + +module.exports = { + ...globalTypedocOptions, + entryPoints: [ + path.join(pathPrefix, "packages/workflows/src/utils/composer/index.ts"), + ], + out: [path.join(pathPrefix, "www/apps/docs/content/references/workflows")], + tsconfig: path.join(__dirname, "extended-tsconfig", "workflows.json"), + name: "Workflows Reference", + indexTitle: "Workflows Reference", + entryDocument: "index.mdx", + hideInPageTOC: true, + hideBreadcrumbs: true, + formatting: { + "*": { + expandMembers: true, + showCommentsAsHeader: true, + sections: { + member_sources_definedIn: false, + reflection_hierarchy: false, + member_sources_inheritedFrom: false, + member_sources_implementationOf: false, + reflection_implementedBy: false, + member_signature_sources: false, + reflection_callable: false, + reflection_indexable: false, + member_signature_title: false, + member_signature_returns: false, + member_getterSetter: false, + }, + parameterStyle: "component", + parameterComponent: "ParameterTypes", + mdxImports: [ + `import ParameterTypes from "@site/src/components/ParameterTypes"`, + ], + frontmatterData: { + displayed_sidebar: "workflowsSidebar", + }, + }, + "index\\.mdx": { + reflectionGroups: { + Namespaces: false, + Enumerations: false, + Classes: false, + Interfaces: false, + "Type Aliases": false, + Variables: false, + "Enumeration Members": false, + }, + }, + functions: { + maxLevel: 1, + }, + "classes/StepResponse": { + reflectionGroups: { + Properties: false, + }, + }, + transform: { + reflectionGroups: { + "Type Parameters": false, + }, + }, + }, + objectLiteralTypeDeclarationStyle: "component", + mdxOutput: true, + maxLevel: 2, + allReflectionsHaveOwnDocument: true, + excludeExternals: true, +} diff --git a/docs-util/packages/typedoc-plugin-custom/src/index.ts b/docs-util/packages/typedoc-plugin-custom/src/index.ts index 7c4bf3348191c..8525ebdd9451b 100644 --- a/docs-util/packages/typedoc-plugin-custom/src/index.ts +++ b/docs-util/packages/typedoc-plugin-custom/src/index.ts @@ -4,6 +4,7 @@ import { load as frontmatterPlugin } from "./frontmatter-plugin" import { load as parseOasSchemaPlugin } from "./parse-oas-schema-plugin" import { load as apiIgnorePlugin } from "./api-ignore" import { load as eslintExamplePlugin } from "./eslint-example" +import { load as signatureModifierPlugin } from "./signature-modifier" export function load(app: Application) { resolveReferencesPluginLoad(app) @@ -11,4 +12,5 @@ export function load(app: Application) { parseOasSchemaPlugin(app) apiIgnorePlugin(app) eslintExamplePlugin(app) + signatureModifierPlugin(app) } diff --git a/docs-util/packages/typedoc-plugin-custom/src/signature-modifier.ts b/docs-util/packages/typedoc-plugin-custom/src/signature-modifier.ts new file mode 100644 index 0000000000000..e335ad47e9c0e --- /dev/null +++ b/docs-util/packages/typedoc-plugin-custom/src/signature-modifier.ts @@ -0,0 +1,21 @@ +import { + Application, + Context, + Converter, + ProjectReflection, + SignatureReflection, +} from "typedoc" + +export function load(app: Application) { + app.converter.on( + Converter.EVENT_CREATE_SIGNATURE, + ( + context: Context, + signature: SignatureReflection | ProjectReflection | undefined + ) => { + if (signature?.comment?.hasModifier("@hideSignature")) { + context.project.removeReflection(signature) + } + } + ) +} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/returns.ts b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/returns.ts index 2c3845fa4414d..557b105917220 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/returns.ts +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/returns.ts @@ -31,13 +31,13 @@ function getReturnFromType( return "" } - const componentItems = returnReflectionComponentFormatter( - reflection.type, - reflection.project || theme.project, - reflection.comment, - 1, - maxLevel - ) + const componentItems = returnReflectionComponentFormatter({ + reflectionType: reflection.type, + project: reflection.project || theme.project, + comment: reflection.comment, + level: 1, + maxLevel, + }) if (parameterStyle === "component") { return `<${parameterComponent} parameters={${JSON.stringify( diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/signature-title.ts b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/signature-title.ts index 3793ff45e173d..0bfebe6f1ebd9 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/signature-title.ts +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/helpers/signature-title.ts @@ -15,7 +15,7 @@ export default function (theme: MarkdownTheme) { theme.getFormattingOptionsForLocation() if (sections && sections.member_signature_title === false) { // only show title if there are more than one signatures - if (!this.parent.signatures || this.parent.signatures?.length <= 1) { + if (!this.parent.signatures || this.parent.signatures.length <= 1) { return "" } } diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs index cf79ca107117a..2a339b5737a75 100755 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.declaration.hbs @@ -12,7 +12,7 @@ {{#if (sectionEnabled "member_declaration_example")}} -{{{example this 3}}} +{{{example this 4}}} {{/if}} @@ -20,7 +20,7 @@ {{#if typeParameters}} -{{titleLevel 3}} Type parameters +{{{titleLevel 4}}} Type Parameters {{#with typeParameters}} @@ -40,7 +40,7 @@ {{#with type.declaration.indexSignature}} -{{titleLevel 3}} Index signature +{{titleLevel 4}} Index signature {{{indexSignatureTitle}}} @@ -58,17 +58,17 @@ {{#if type.declaration.children}} -{{titleLevel 3}} Call signature +{{{titleLevel 4}}} Call signature {{else}} -{{titleLevel 3}} Type declaration +{{{titleLevel 4}}} Type declaration {{/if}} {{#each type.declaration.signatures}} -{{> member.signature showSources=false }} +{{> member.signature showSources=false commentLevel=5 }} {{/each}} @@ -82,7 +82,7 @@ {{#with type.declaration}} -{{titleLevel 3}} Type declaration +{{{titleLevel 4}}} Type declaration {{/with}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.getterSetter.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.getterSetter.hbs index 0657dc1fbda8e..746961b44ccb5 100755 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.getterSetter.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.getterSetter.hbs @@ -4,7 +4,7 @@ {{#with getSignature}} -{{> member.signature accessor="get" showSources=true }} +{{> member.signature accessor="get" showSources=true commentLevel=4 }} {{/with}} @@ -18,7 +18,7 @@ {{#with setSignature}} -{{> member.signature accessor="set" showSources=true }} +{{> member.signature accessor="set" showSources=true commentLevel=4 }} {{/with}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.hbs index 5062e71e6c834..91c0a4f0dd17d 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.hbs @@ -2,7 +2,7 @@ {{#if name}} -{{titleLevel 3}} {{#ifNamedAnchors}} {{/ifNamedAnchors}}{{ escape name }} +{{titleLevel 4}} {{#ifNamedAnchors}} {{/ifNamedAnchors}}{{ escape name }} {{/if}} @@ -14,7 +14,7 @@ {{#each signatures}} -{{> member.signature showSources=true }} +{{> member.signature showSources=true commentLevel=../commentLevel }} {{/each}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.signature.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.signature.hbs index b8d21bba97fa2..7a50c41def3a3 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.signature.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/member.signature.hbs @@ -14,10 +14,18 @@ {{/if}} +{{#if (sectionEnabled "member_signature_example")}} + +{{{example this commentLevel}}} + +{{/if}} + {{#if (sectionEnabled "member_signature_typeParameters")}} {{#if typeParameters}} +{{{titleLevel commentLevel}}} Type Parameters + {{#with typeParameters}} {{{typeParameter}}} @@ -28,25 +36,11 @@ {{/if}} -{{#if (sectionEnabled "member_signature_example")}} - -{{{example this 4}}} - -{{/if}} - {{#if (sectionEnabled "member_signature_parameters")}} {{#if parameters}} -{{#if showSources}} - -{{{titleLevel 4}}} Parameters - -{{else}} - -{{{titleLevel 5}}} Parameters - -{{/if}} +{{{titleLevel commentLevel}}} Parameters {{#with parameters}} @@ -62,15 +56,7 @@ {{#if type}} -{{#if showSources}} - -{{{titleLevel 4}}} Returns - -{{else}} - -{{{titleLevel 5}}} Returns - -{{/if}} +{{{titleLevel commentLevel}}} Returns {{#if (sectionEnabled "member_signature_returns")}} @@ -92,7 +78,7 @@ {{#each declaration.signatures}} -{{> member.signature showSources=false }} +{{> member.signature showSources=false commentLevel=commentLevel }} {{/each}} @@ -126,7 +112,7 @@ {{#if hasVisibleComponent}} -{{{comments this false true 4 ..}}} +{{{comments this false true commentLevel ..}}} {{/if}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.group.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.group.hbs index 89b24733a98d1..b32fb78432f79 100755 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.group.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.group.hbs @@ -26,7 +26,7 @@ ___ {{#each children}} -{{> member}} +{{> member commentLevel=5}} {{/each}} @@ -54,7 +54,7 @@ ___ {{#each children}} -{{> member}} +{{> member commentLevel=5}} {{/each}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.hbs index 08f7e8134a8b5..c00601347a3ba 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/members.hbs @@ -16,7 +16,7 @@ {{#unless hasOwnDocument}} -{{> member}} +{{> member commentLevel=4}} {{/unless}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/section-title.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/section-title.hbs new file mode 100644 index 0000000000000..e863067f41ab3 --- /dev/null +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/partials/section-title.hbs @@ -0,0 +1,9 @@ +{{#if showSources}} + +{{{titleLevel 4}}} {{{title}}} + +{{else}} + +{{{titleLevel 5}}} {{{title}}} + +{{/if}} \ No newline at end of file diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.hbs index 7ae033c57476d..6c63ea1f9cb46 100755 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.hbs @@ -94,7 +94,7 @@ ### {{name}} -{{> member.signature showSources=true }} +{{> member.signature showSources=true commentLevel=4 }} {{/each}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.member.hbs b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.member.hbs index 78129be63b6a5..8b2a6554b242f 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.member.hbs +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/resources/templates/reflection.member.hbs @@ -4,6 +4,6 @@ {{#with model}} -{{> member}} +{{> member showSources=false commentLevel=4}} {{/with}} diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/theme.ts b/docs-util/packages/typedoc-plugin-markdown-medusa/src/theme.ts index 6a501e56e42af..1b739b1efbb17 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/theme.ts +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/theme.ts @@ -5,7 +5,6 @@ import { PageEvent, ProjectReflection, Reflection, - ReflectionGroup, ReflectionKind, RenderTemplate, Renderer, @@ -359,22 +358,45 @@ export class MarkdownTheme extends Theme { this.location = page.url this.reflection = page.model instanceof DeclarationReflection ? page.model : undefined - const options = this.getFormattingOptionsForLocation() - if (this.reflection && this.reflection.groups) { - // filter out unwanted groups - const tempGroups: ReflectionGroup[] = [] - this.reflection.groups.forEach((reflectionGroup) => { - if ( - !options.reflectionGroups || - !(reflectionGroup.title in options.reflectionGroups) || - options.reflectionGroups[reflectionGroup.title] - ) { - tempGroups.push(reflectionGroup) - } - }) - this.reflection.groups = tempGroups + if ( + page.model instanceof DeclarationReflection || + page.model instanceof ProjectReflection + ) { + this.removeGroups(page.model) + } + + if ( + this.reflection instanceof DeclarationReflection && + this.reflection.signatures + ) { + // check if any of its signature has the `@mainSignature` tag + // and if so remove other signatures + const mainSignatureIndex = this.reflection.signatures.findIndex( + (signature) => signature.comment?.hasModifier("@mainSignature") + ) + + if (mainSignatureIndex !== -1) { + const mainSignature = this.reflection.signatures[mainSignatureIndex] + this.reflection.signatures = [mainSignature] + } + } + } + + protected removeGroups(model?: DeclarationReflection | ProjectReflection) { + if (!model?.groups) { + return } + + const options = this.getFormattingOptionsForLocation() + + model.groups = model.groups.filter((reflectionGroup) => { + return ( + !options.reflectionGroups || + !(reflectionGroup.title in options.reflectionGroups) || + options.reflectionGroups[reflectionGroup.title] + ) + }) } get globalsFile() { diff --git a/docs-util/packages/typedoc-plugin-markdown-medusa/src/utils/return-reflection-formatter.ts b/docs-util/packages/typedoc-plugin-markdown-medusa/src/utils/return-reflection-formatter.ts index 1155fe28526df..eb930e1cdf2cc 100644 --- a/docs-util/packages/typedoc-plugin-markdown-medusa/src/utils/return-reflection-formatter.ts +++ b/docs-util/packages/typedoc-plugin-markdown-medusa/src/utils/return-reflection-formatter.ts @@ -4,6 +4,7 @@ import { ProjectReflection, ReflectionFlags, SomeType, + TypeParameterReflection, } from "typedoc" import * as Handlebars from "handlebars" import getType from "./type-utils" @@ -14,19 +15,27 @@ import { } from "./reflection-formatter" import { MarkdownTheme } from "../theme" -export function returnReflectionComponentFormatter( - reflectionType: SomeType, - project: ProjectReflection, - comment?: Comment, - level = 1, +type ReturnReflectionComponentFormatterParams = { + reflectionType: SomeType + project: ProjectReflection + comment?: Comment + level: number maxLevel?: number | undefined -): Parameter[] { +} + +export function returnReflectionComponentFormatter({ + reflectionType, + project, + comment, + level = 1, + maxLevel, +}: ReturnReflectionComponentFormatterParams): Parameter[] { const typeName = getType(reflectionType, "object", false, true) const type = getType(reflectionType, "object") const componentItem: Parameter[] = [] + const canRetrieveChildren = level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL) if (reflectionType.type === "reference") { - // put type name as a title and its referenced items as children. - if (reflectionType.typeArguments) { + if (reflectionType.typeArguments || reflectionType.refersToTypeParameter) { const parentKey = componentItem.push({ name: "name" in reflectionType ? reflectionType.name : typeName, type, @@ -45,21 +54,30 @@ export function returnReflectionComponentFormatter( featureFlag: Handlebars.helpers.featureFlag(comment), children: [], }) + const typeArgs = reflectionType.typeArguments + ? reflectionType.typeArguments + : "typeParameters" in reflectionType + ? (reflectionType.typeParameters as TypeParameterReflection[]) + : undefined if ( - !isOnlyVoid(reflectionType.typeArguments) && - level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL) + typeArgs && + !isOnlyVoid(typeArgs as unknown as SomeType[]) && + canRetrieveChildren ) { - reflectionType.typeArguments.forEach((typeArg) => { - const typeArgComponent = returnReflectionComponentFormatter( - typeArg, - project, - undefined, - level + 1, - maxLevel - ) - if (typeArgComponent.length) { - componentItem[parentKey - 1].children?.push(...typeArgComponent) + typeArgs.forEach((typeArg) => { + const reflectionTypeArg = + typeArg instanceof TypeParameterReflection ? typeArg.type : typeArg + if (!reflectionTypeArg) { + return } + const typeArgComponent = returnReflectionComponentFormatter({ + reflectionType: reflectionTypeArg, + project, + level: level + 1, + maxLevel, + }) + + componentItem[parentKey - 1].children?.push(...typeArgComponent) }) } } else { @@ -107,17 +125,14 @@ export function returnReflectionComponentFormatter( featureFlag: Handlebars.helpers.featureFlag(comment), children: [], }) - if (level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL)) { - const elementTypeItem = returnReflectionComponentFormatter( - reflectionType.elementType, + if (canRetrieveChildren) { + const elementTypeItem = returnReflectionComponentFormatter({ + reflectionType: reflectionType.elementType, project, - undefined, - level + 1, - maxLevel - ) - if (elementTypeItem.length) { - componentItem[parentKey - 1].children?.push(...elementTypeItem) - } + level: level + 1, + maxLevel, + }) + componentItem[parentKey - 1].children?.push(...elementTypeItem) } } else if (reflectionType.type === "tuple") { let pushTo: Parameter[] = [] @@ -145,18 +160,15 @@ export function returnReflectionComponentFormatter( } else { pushTo = componentItem } - if (level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL)) { + if (canRetrieveChildren) { reflectionType.elements.forEach((element) => { - const elementTypeItem = returnReflectionComponentFormatter( - element, + const elementTypeItem = returnReflectionComponentFormatter({ + reflectionType: element, project, - undefined, - level + 1, - maxLevel - ) - if (elementTypeItem.length) { - pushTo.push(...elementTypeItem) - } + level: level + 1, + maxLevel, + }) + pushTo.push(...elementTypeItem) }) } } else { diff --git a/docs-util/packages/utils/src/get-type-children.ts b/docs-util/packages/utils/src/get-type-children.ts index bfe4b143f76cc..e3e79dcb25c19 100644 --- a/docs-util/packages/utils/src/get-type-children.ts +++ b/docs-util/packages/utils/src/get-type-children.ts @@ -65,7 +65,15 @@ export function getTypeChildren( children = getTypeChildren(reflectionType.elementType, project) } - return children + return filterChildren(children) +} + +const REJECTED_CHILDREN_NAMES = ["__type"] + +function filterChildren(children: DeclarationReflection[]) { + return children.filter( + (child) => !REJECTED_CHILDREN_NAMES.includes(child.name) + ) } function removeChild(name: unknown, children: DeclarationReflection[]) { diff --git a/integration-tests/environment-helpers/use-db.js b/integration-tests/environment-helpers/use-db.js index b5ccf47ff0e03..261ccfac95521 100644 --- a/integration-tests/environment-helpers/use-db.js +++ b/integration-tests/environment-helpers/use-db.js @@ -32,6 +32,8 @@ const keepTables = [ "payment_provider", "country", "currency", + "migrations", + "mikro_orm_migrations", ] const DbTestUtil = { @@ -52,21 +54,23 @@ const DbTestUtil = { teardown: async function ({ forceDelete } = {}) { forceDelete = forceDelete || [] - const entities = this.db_.entityMetadatas const manager = this.db_.manager await manager.query(`SET session_replication_role = 'replica';`) + const tableNames = await manager.query(`SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public';`) - for (const entity of entities) { + for (const { table_name } of tableNames) { if ( - keepTables.includes(entity.tableName) && - !forceDelete.includes(entity.tableName) + keepTables.includes(table_name) && + !forceDelete.includes(table_name) ) { continue } await manager.query(`DELETE - FROM "${entity.tableName}";`) + FROM "${table_name}";`) } await manager.query(`SET session_replication_role = 'origin';`) diff --git a/integration-tests/factories/index.ts b/integration-tests/factories/index.ts index 40a248a49467f..5240f082972c3 100644 --- a/integration-tests/factories/index.ts +++ b/integration-tests/factories/index.ts @@ -2,6 +2,7 @@ export * from "./simple-batch-job-factory" export * from "./simple-cart-factory" export * from "./simple-custom-shipping-option-factory" export * from "./simple-customer-factory" +export * from "./simple-customer-group-factory" export * from "./simple-discount-factory" export * from "./simple-gift-card-factory" export * from "./simple-line-item-factory" @@ -22,5 +23,5 @@ export * from "./simple-shipping-method-factory" export * from "./simple-shipping-option-factory" export * from "./simple-shipping-profile-factory" export * from "./simple-shipping-tax-rate-factory" -export * from "./simple-tax-rate-factory" export * from "./simple-store-factory" +export * from "./simple-tax-rate-factory" diff --git a/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts new file mode 100644 index 0000000000000..1caaef078d067 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts @@ -0,0 +1,191 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("POST /admin/price-lists/:id/prices/batch", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should update money amounts if variant id is present in prices", async () => { + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + }, + ]) + + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + prices: [ + { + variant_id: variant.id, + amount: 5000, + currency_code: "usd", + }, + ], + } + + await api.post( + `admin/price-lists/${priceList.id}/prices/batch`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts new file mode 100644 index 0000000000000..831251c1752e5 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts @@ -0,0 +1,191 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleCustomerGroupFactory, + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { IPricingModuleService } from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("POST /admin/price-lists", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + await simpleCustomerGroupFactory(dbConnection, { + id: "customer-group-1", + name: "Test Group", + }) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should create price list and money amounts", async () => { + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [{ id: "customer-group-1" }], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + + let response = await api.get( + `/admin/price-lists/${result.data.price_list.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: null, + ends_at: null, + customer_groups: [ + { + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "Test Group", + metadata: null, + }, + ], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 400, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts new file mode 100644 index 0000000000000..ec8e17fd03fd2 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts @@ -0,0 +1,181 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { IPricingModuleService } from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { AxiosInstance } from "axios" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("DELETE /admin/price-lists/:id/products/:productId/batch", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant1 + let priceSet + let priceListId + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + const api = useApi()! as AxiosInstance + + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant1 = product.variants[0] + + priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant1.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant1.id, + currency_code: "usd", + }, + ], + } + + const priceListResult = await api.post( + `admin/price-lists`, + data, + adminHeaders + ) + priceListId = priceListResult.data.price_list.id + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should delete prices in batch based on product ids", async () => { + const api = useApi()! as AxiosInstance + + let priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + expect(priceSetMoneyAmounts.length).toEqual(2) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/products/prices/batch`, + { + headers: adminHeaders.headers, + data: { + product_ids: [product.id], + }, + } + ) + expect(deleteRes.status).toEqual(200) + + priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + + expect(priceSetMoneyAmounts.length).toEqual(1) + expect(priceSetMoneyAmounts).toEqual([ + expect.objectContaining({ + price_list: null, + }), + ]) + }) + + it("should delete prices based on single product id", async () => { + const api = useApi()! as AxiosInstance + + let priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + expect(priceSetMoneyAmounts.length).toEqual(2) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/products/${product.id}/prices`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + + expect(priceSetMoneyAmounts.length).toEqual(1) + expect(priceSetMoneyAmounts).toEqual([ + expect.objectContaining({ + price_list: null, + }), + ]) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts new file mode 100644 index 0000000000000..cc0639a075d98 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts @@ -0,0 +1,132 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { IPricingModuleService } from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should delete all prices based on product variant ids", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + const priceListId = result.data.price_list.id + + let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/variants/${variant.id}/prices`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(0) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts new file mode 100644 index 0000000000000..9924193e3e8d0 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts @@ -0,0 +1,146 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { IPricingModuleService } from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("DELETE /admin/price-lists/:id", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should delete price list prices by money amount ids", async () => { + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + name: "test price list", + description: "test", + type: "override", + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + { + amount: 4000, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const res = await api.post(`admin/price-lists`, data, adminHeaders) + + const priceListId = res.data.price_list.id + let psmas = await pricingModuleService.listPriceSetMoneyAmounts( + { + price_list_id: [priceListId], + }, + { relations: ["money_amount"] } + ) + + expect(psmas.length).toEqual(2) + + const deletePrice = psmas[0].money_amount + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/prices/batch`, + { + data: { + price_ids: [deletePrice?.id], + }, + ...adminHeaders, + } + ) + expect(deleteRes.status).toEqual(200) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts new file mode 100644 index 0000000000000..47064fed15a20 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts @@ -0,0 +1,145 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { IPricingModuleService } from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("DELETE /admin/price-lists/:id", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should delete price list and money amounts", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + const priceListId = result.data.price_list.id + + const getResponse = await api.get( + `/admin/price-lists/${priceListId}`, + adminHeaders + ) + expect(getResponse.status).toEqual(200) + + let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + const afterDelete = await api + .get(`/admin/price-lists/${priceListId}`, adminHeaders) + .catch((err) => { + return err + }) + expect(afterDelete.response.status).toEqual(404) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(0) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts new file mode 100644 index 0000000000000..9eed1dd60766c --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts @@ -0,0 +1,204 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { simpleProductFactory } from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("GET /admin/price-lists/:id", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should get price list and its money amounts with variants", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + rules: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], + }, + ]) + + await pricingModuleService.createPriceLists([ + { + title: "test price list 1", + description: "test 1", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], + }, + ]) + + const api = useApi() as any + + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) + }) + + it("should throw an error when price list is not found", async () => { + const api = useApi() as any + + const error = await api + .get(`/admin/price-lists/does-not-exist`, adminHeaders) + .catch((e) => e) + + expect(error.response.status).toBe(404) + expect(error.response.data).toEqual({ + type: "not_found", + message: "Price list with id: does-not-exist was not found", + }) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts new file mode 100644 index 0000000000000..1395fa75d854d --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts @@ -0,0 +1,274 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { simpleProductFactory } from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("GET /admin/price-lists/:id/products", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let product2 + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + title: "uniquely fun product", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + + product2 = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant-2", + title: "uniquely fun product 2", + variants: [ + { + options: [{ option_id: "test-product-option-2", value: "test 2" }], + }, + ], + options: [ + { + id: "test-product-option-2", + title: "Test option 2", + }, + ], + }) + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should list all products in a price list", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + rules: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], + }, + ]) + + const api = useApi() as any + + let response = await api.get( + `/admin/price-lists/${priceList.id}/products`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + title: expect.any(String), + handle: expect.any(String), + subtitle: null, + description: null, + is_giftcard: false, + status: "draft", + thumbnail: null, + weight: null, + length: null, + height: null, + width: null, + origin_country: null, + hs_code: null, + mid_code: null, + material: null, + collection_id: null, + collection: null, + type_id: null, + type: null, + discountable: true, + external_id: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + metadata: null, + }), + ]) + + response = await api.get( + `/admin/products?price_list_id[]=${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + title: expect.any(String), + handle: expect.any(String), + subtitle: null, + description: null, + is_giftcard: false, + status: "draft", + thumbnail: null, + weight: null, + length: null, + height: null, + width: null, + origin_country: null, + hs_code: null, + mid_code: null, + material: null, + collection_id: null, + collection: null, + type_id: null, + type: null, + discountable: true, + external_id: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + metadata: null, + }), + ]) + }) + + it("should list all products constrained by search query in a price list", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + rules: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], + }, + ]) + + const api = useApi() as any + + let response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=shouldnotreturnanything`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(0) + expect(response.data.products).toEqual([]) + + response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=uniquely`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + }), + ]) + + response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + }), + ]) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts new file mode 100644 index 0000000000000..fbe8a9830f2c6 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts @@ -0,0 +1,170 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { simpleProductFactory } from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("GET /admin/price-lists", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should get price list and its money amounts with variants", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + rules: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], + }, + ]) + + const api = useApi() as any + + const response = await api.get(`/admin/price-lists`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.price_lists).toEqual([ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }), + ]) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts new file mode 100644 index 0000000000000..20dfecf877b24 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts @@ -0,0 +1,226 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleCustomerGroupFactory, + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("POST /admin/price-lists/:id", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let variant2 + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + await simpleCustomerGroupFactory(dbConnection, { + id: "customer-group-2", + name: "Test Group 2", + }) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + { + options: [{ option_id: "test-product-option-2", value: "test 2" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + { + id: "test-product-option-2", + title: "Test option 2", + }, + ], + }) + + variant = product.variants[0] + variant2 = product.variants[1] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should update price lists successfully with prices", async () => { + const var2PriceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant2.id, + prices: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 3000, + currency_code: "usd", + price_set_id: var2PriceSet.id, + }, + ], + }, + ]) + + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + ], + }) + + const api = useApi() as any + const data = { + name: "new price list name", + description: "new price list description", + customer_groups: [{ id: "customer-group-2" }], + prices: [ + { + variant_id: variant.id, + amount: 5000, + currency_code: "usd", + }, + { + id: priceList?.price_set_money_amounts?.[0].money_amount?.id, + amount: 6000, + currency_code: "usd", + variant_id: variant2.id, + }, + ], + } + + await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders) + + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "new price list name", + description: "new price list description", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [ + { + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "Test Group 2", + metadata: null, + }, + ], + prices: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: priceList.id, + region_id: null, + variant: expect.objectContaining({ + id: variant.id, + }), + variant_id: variant.id, + }), + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 6000, + min_quantity: null, + max_quantity: null, + price_list_id: priceList.id, + region_id: null, + variant: expect.objectContaining({ + id: variant2.id, + }), + variant_id: variant2.id, + }), + ]), + }) + ) + }) +}) diff --git a/integration-tests/plugins/__tests__/price-lists/store/get-product.ts b/integration-tests/plugins/__tests__/price-lists/store/get-product.ts new file mode 100644 index 0000000000000..ad5915f910e02 --- /dev/null +++ b/integration-tests/plugins/__tests__/price-lists/store/get-product.ts @@ -0,0 +1,289 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleCustomerFactory, + simpleCustomerGroupFactory, + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { + IPricingModuleService, + PriceListStatus, + PriceListType, +} from "@medusajs/types" +import { AxiosInstance } from "axios" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("GET /store/products/:id", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + let priceSetId + let pricingModuleService: IPricingModuleService + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + status: "published", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + rules: {}, + }, + { + amount: 4000, + currency_code: "usd", + rules: {}, + }, + ], + rules: [], + }) + + priceSetId = priceSet.id + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should get product and its prices from price-list created through the price list workflow", async () => { + const api = useApi()! as AxiosInstance + + const priceListResponse = await api.post( + `/admin/price-lists`, + { + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], + }, + adminHeaders + ) + + let response = await api.get( + `/store/products/${product.id}?currency_code=usd` + ) + + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toHaveLength(2) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + expect.objectContaining({ + currency_code: "usd", + amount: 2500, + min_quantity: null, + max_quantity: null, + price_list_id: priceListResponse.data.price_list.id, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 2500, + calculated_price_type: "sale", + }) + ) + }) + + it("should not list prices from price-list with customer groups if not logged in", async () => { + const api = useApi()! as AxiosInstance + + const { id: customerGroupId } = await simpleCustomerGroupFactory( + dbConnection + ) + + const priceListResponse = await api.post( + `/admin/price-lists`, + { + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], + customer_groups: [{ id: customerGroupId }], + }, + adminHeaders + ) + + let response = await api.get( + `/store/products/${product.id}?currency_code=usd` + ) + + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 3000, + calculated_price_type: null, + }) + ) + }) + + it("should list prices from price-list with customer groups", async () => { + const api = useApi()! as AxiosInstance + + await simpleCustomerFactory(dbConnection, { + id: "test-customer-5-pl", + email: "test5@email-pl.com", + first_name: "John", + last_name: "Deere", + password_hash: + "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" + has_account: true, + groups: [{ id: "customer-group-1" }], + }) + + const authResponse = await api.post("/store/auth", { + email: "test5@email-pl.com", + password: "test", + }) + + const [authCookie] = authResponse.headers["set-cookie"][0].split(";") + + const priceListResponse = await api.post( + `/admin/price-lists`, + { + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], + customer_groups: [{ id: "customer-group-1" }], + }, + adminHeaders + ) + + let response = await api.get( + `/store/products/${product.id}?currency_code=usd`, + { + headers: { + Cookie: authCookie, + }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toHaveLength(2) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + expect.objectContaining({ + currency_code: "usd", + amount: 2500, + min_quantity: null, + max_quantity: null, + price_list_id: priceListResponse.data.price_list.id, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 2500, + calculated_price_type: "sale", + }) + ) + }) +}) diff --git a/integration-tests/plugins/__tests__/pricing/get-product.ts b/integration-tests/plugins/__tests__/pricing/get-product.ts index 0e7a95912867b..2d68c82f4dd07 100644 --- a/integration-tests/plugins/__tests__/pricing/get-product.ts +++ b/integration-tests/plugins/__tests__/pricing/get-product.ts @@ -8,6 +8,7 @@ import path from "path" import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" import { getContainer } from "../../../environment-helpers/use-container" import adminSeeder from "../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../helpers/create-default-rule-types" jest.setTimeout(5000000) @@ -46,6 +47,7 @@ describe("Link Modules", () => { }) beforeEach(async () => { + await createDefaultRuleTypes(medusaContainer) await adminSeeder(dbConnection) await simpleRegionFactory(dbConnection, { id: "region-1", diff --git a/integration-tests/plugins/__tests__/product/admin/create-product-variant.spec.ts b/integration-tests/plugins/__tests__/product/admin/create-product-variant.spec.ts new file mode 100644 index 0000000000000..b4482f482a540 --- /dev/null +++ b/integration-tests/plugins/__tests__/product/admin/create-product-variant.spec.ts @@ -0,0 +1,205 @@ +import { useApi } from "../../../../environment-helpers/use-api" +import { getContainer } from "../../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../../environment-helpers/use-db" +import { + simpleProductFactory, + simpleRegionFactory, +} from "../../../../factories" + +import { PricingModuleService } from "@medusajs/pricing" +import { ProductModuleService } from "@medusajs/product" +import { AxiosInstance } from "axios" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import adminSeeder from "../../../../helpers/admin-seeder" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +describe("POST /admin/products/:id/variants", () => { + let dbConnection + let appContainer + let shutdownServer + let product + let variant + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should create a product variant with its price sets and prices through the workflow", async () => { + const api = useApi()! as AxiosInstance + const data = { + title: "test variant create", + prices: [ + { + amount: 66600, + region_id: "test-region", + }, + { + amount: 55500, + currency_code: "usd", + region_id: null, + }, + ], + material: "boo", + mid_code: "234asdfadsf", + hs_code: "asdfasdf234", + origin_country: "DE", + sku: "asdf", + ean: "234", + upc: "234", + barcode: "asdf", + inventory_quantity: 234, + manage_inventory: true, + allow_backorder: true, + weight: 234, + width: 234, + height: 234, + length: 234, + metadata: { asdf: "asdf" }, + options: [{ option_id: "test-product-option-1", value: "test option" }], + } + + let response = await api.post( + `/admin/products/${product.id}/variants`, + data, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( + expect.objectContaining({ + id: expect.any(String), + variants: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + title: "test variant create", + prices: expect.arrayContaining([ + expect.objectContaining({ + amount: 66600, + currency_code: "usd", + region_id: "test-region", + }), + expect.objectContaining({ + amount: 55500, + currency_code: "usd", + }), + ]), + }), + ]), + }) + ) + }) + + it("should compensate creating product variants when error throws in future step", async () => { + jest + .spyOn(PricingModuleService.prototype, "create") + .mockImplementation(() => { + throw new Error("Random Error") + }) + + const productSpy = jest.spyOn( + ProductModuleService.prototype, + "deleteVariants" + ) + + const api = useApi()! as AxiosInstance + const data = { + title: "test variant create", + prices: [ + { + amount: 66600, + region_id: "test-region", + }, + { + amount: 55500, + currency_code: "usd", + region_id: null, + }, + ], + material: "boo", + mid_code: "234asdfadsf", + hs_code: "asdfasdf234", + origin_country: "DE", + sku: "asdf", + ean: "234", + upc: "234", + barcode: "asdf", + inventory_quantity: 234, + manage_inventory: true, + allow_backorder: true, + weight: 234, + width: 234, + height: 234, + length: 234, + metadata: { asdf: "asdf" }, + options: [{ option_id: "test-product-option-1", value: "test option" }], + } + + await api + .post(`/admin/products/${product.id}/variants`, data, adminHeaders) + .catch((e) => e) + + expect(productSpy).toBeCalledWith([expect.any(String)]) + + const getProductResponse = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + expect(getProductResponse.data.product.variants).toHaveLength(1) + }) +}) diff --git a/integration-tests/plugins/__tests__/product/admin/create-product.ts b/integration-tests/plugins/__tests__/product/admin/create-product.ts index 7471d5ee45a65..a286b03e77f5e 100644 --- a/integration-tests/plugins/__tests__/product/admin/create-product.ts +++ b/integration-tests/plugins/__tests__/product/admin/create-product.ts @@ -1,11 +1,13 @@ import { initDb, useDb } from "../../../../environment-helpers/use-db" import { Region } from "@medusajs/medusa" +import { IPricingModuleService } from "@medusajs/types" import { AxiosInstance } from "axios" import path from "path" import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import { useApi } from "../../../../environment-helpers/use-api" import { getContainer } from "../../../../environment-helpers/use-container" +import { simpleSalesChannelFactory } from "../../../../factories" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" @@ -21,7 +23,7 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe("[Product & Pricing Module] POST /admin/products", () => { +describe("POST /admin/products", () => { let dbConnection let appContainer let shutdownServer @@ -50,6 +52,8 @@ describe("[Product & Pricing Module] POST /admin/products", () => { currency_code: "usd", tax_rate: 0, }) + + await simpleSalesChannelFactory(dbConnection, { is_default: true }) }) afterEach(async () => { @@ -110,5 +114,12 @@ describe("[Product & Pricing Module] POST /admin/products", () => { ]), }), }) + + const pricingModuleService: IPricingModuleService = appContainer.resolve( + "pricingModuleService" + ) + + const [_, count] = await pricingModuleService.listAndCount() + expect(count).toEqual(1) }) }) diff --git a/integration-tests/plugins/__tests__/product/admin/index.ts b/integration-tests/plugins/__tests__/product/admin/index.ts index c46ace8b44d0f..3d388e03aba65 100644 --- a/integration-tests/plugins/__tests__/product/admin/index.ts +++ b/integration-tests/plugins/__tests__/product/admin/index.ts @@ -441,6 +441,7 @@ describe("/admin/products", () => { beforeEach(async () => { await productSeeder(dbConnection) await adminSeeder(dbConnection) + await createDefaultRuleTypes(medusaContainer) await simpleSalesChannelFactory(dbConnection, { name: "Default channel", diff --git a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts index 590d340457107..2f76bdd06c6d6 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts @@ -1,5 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, @@ -7,11 +5,13 @@ import { } from "../../../../factories" import { AxiosInstance } from "axios" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { getContainer } from "../../../../environment-helpers/use-container" +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import { useApi } from "../../../../environment-helpers/use-api" jest.setTimeout(50000) @@ -25,7 +25,7 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () => { +describe("POST /admin/products/:id/variants/:id", () => { let dbConnection let appContainer let shutdownServer @@ -62,6 +62,9 @@ describe("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () { options: [{ option_id: "test-product-option-1", value: "test" }], }, + { + options: [{ option_id: "test-product-option-1", value: "test 2" }], + }, ], options: [ { @@ -250,4 +253,231 @@ describe("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () }) ) }) + + it("should update variant option value", async () => { + const api = useApi()! as AxiosInstance + + const data = { + options: [ + { + option_id: "test-product-option-1", + value: "updated", + }, + ], + } + + await api.post( + `/admin/products/${product.id}/variants/${variant.id}`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( + expect.objectContaining({ + id: expect.any(String), + variants: expect.arrayContaining([ + expect.objectContaining({ + id: variant.id, + options: [ + expect.objectContaining({ + option_id: "test-product-option-1", + value: "updated", + }), + ], + }), + expect.objectContaining({ + id: product.variants[1].id, + options: [ + expect.objectContaining({ + option_id: "test-product-option-1", + value: "test 2", + }), + ], + }), + ]), + }) + ) + }) + + it("should update variant metadata", async () => { + const api = useApi()! as AxiosInstance + + const data = { + metadata: { + test: "string", + }, + } + + await api.post( + `/admin/products/${product.id}/variants/${variant.id}`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( + expect.objectContaining({ + id: expect.any(String), + variants: expect.arrayContaining([ + expect.objectContaining({ + id: variant.id, + metadata: { + test: "string", + }, + }), + ]), + }) + ) + }) + + it("should remove options not present in update", async () => { + const api = useApi()! as AxiosInstance + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-multiple-options", + variants: [ + { + options: [ + { option_id: "test-product-multi-option-1", value: "test" }, + { option_id: "test-product-multi-option-2", value: "test value" }, + ], + }, + ], + options: [ + { + id: "test-product-multi-option-1", + title: "Test option 1", + }, + { + id: "test-product-multi-option-2", + title: "Test option 2", + }, + ], + }) + + variant = product.variants[0] + + const data = { + options: [ + { + option_id: "test-product-multi-option-1", + value: "updated", + }, + ], + } + + await api.post( + `/admin/products/${product.id}/variants/${variant.id}`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( + expect.objectContaining({ + id: expect.any(String), + variants: [ + expect.objectContaining({ + id: variant.id, + options: [ + expect.objectContaining({ + option_id: "test-product-multi-option-1", + value: "updated", + }), + ], + }), + ], + }) + ) + }) + + it("should update several options in the same api call", async () => { + const api = useApi()! as AxiosInstance + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-multiple-options", + variants: [ + { + options: [ + { option_id: "test-product-multi-option-1", value: "test" }, + { option_id: "test-product-multi-option-2", value: "test value" }, + ], + }, + ], + options: [ + { + id: "test-product-multi-option-1", + title: "Test option 1", + }, + { + id: "test-product-multi-option-2", + title: "Test option 2", + }, + ], + }) + + variant = product.variants[0] + + const data = { + options: [ + { + option_id: "test-product-multi-option-1", + value: "updated", + }, + { + option_id: "test-product-multi-option-2", + value: "updated 2", + }, + ], + } + + await api.post( + `/admin/products/${product.id}/variants/${variant.id}`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( + expect.objectContaining({ + id: expect.any(String), + variants: [ + expect.objectContaining({ + id: variant.id, + options: [ + expect.objectContaining({ + option_id: "test-product-multi-option-1", + value: "updated", + }), + expect.objectContaining({ + option_id: "test-product-multi-option-2", + value: "updated 2", + }), + ], + }), + ], + }) + ) + }) }) diff --git a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts index b631eb0a1564b..db9750f26429d 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts @@ -23,7 +23,7 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe("[Product & Pricing Module] POST /admin/products/:id", () => { +describe("POST /admin/products/:id", () => { let dbConnection let appContainer let shutdownServer @@ -109,10 +109,11 @@ describe("[Product & Pricing Module] POST /admin/products/:id", () => { ) expect(response.status).toEqual(200) + expect(response.data.product.variants).toHaveLength(1) expect(response.data.product).toEqual( expect.objectContaining({ id: expect.any(String), - variants: expect.arrayContaining([ + variants: [ expect.objectContaining({ id: variant.id, title: "test variant update", @@ -128,7 +129,7 @@ describe("[Product & Pricing Module] POST /admin/products/:id", () => { }), ]), }), - ]), + ], }) ) }) diff --git a/integration-tests/plugins/__tests__/workflows/utils/composer/compose.ts b/integration-tests/plugins/__tests__/workflows/utils/composer/compose.ts new file mode 100644 index 0000000000000..0bec8edef9cc0 --- /dev/null +++ b/integration-tests/plugins/__tests__/workflows/utils/composer/compose.ts @@ -0,0 +1,1882 @@ +import { promiseAll } from "@medusajs/utils" +import { + createStep, + createWorkflow, + hook, + parallelize, + StepResponse, + transform, +} from "@medusajs/workflows" + +jest.setTimeout(30000) + +describe("Workflow composer", function () { + describe("Using steps returning plain values", function () { + afterEach(async () => { + jest.clearAllMocks() + }) + + it("should compose a new workflow and execute it", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [workflowInput], + obj: "return from 1", + }, + two: { + inputs: [ + { + inputs: [workflowInput], + obj: "return from 1", + }, + ], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [workflowInput], + obj: "return from 1", + }, + two: { + inputs: [ + { + inputs: [workflowInput], + obj: "return from 1", + }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows sequentially and execute them sequentially", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflow2 = createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + const workflow2Input = { test: "payload2" } + const { result: workflow2Result } = await workflow2().run({ + input: workflow2Input, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [{ test: "payload1" }], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [{ test: "payload2" }], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows concurrently and execute them sequentially", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const [workflow, workflow2] = await promiseAll([ + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + + createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + ]) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + const workflow2Input = { test: "payload2" } + const { result: workflow2Result } = await workflow2().run({ + input: workflow2Input, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [workflow2Input], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows concurrently and execute them concurrently", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const [workflow, workflow2] = await promiseAll([ + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + + createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + ]) + + const workflowInput = { test: "payload1" } + const workflow2Input = { test: "payload2" } + + const [{ result: workflowResult }, { result: workflow2Result }] = + await promiseAll([ + workflow().run({ + input: workflowInput, + }), + workflow2().run({ + input: workflow2Input, + }), + ]) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + expect(mockStep1Fn.mock.calls[1]).toHaveLength(2) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [workflow2Input], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose a new workflow and execute it multiple times concurrently", async () => { + const mockStep1Fn = jest + .fn() + .mockImplementation(function (input, context) { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation(function (...inputs) { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation(function (...inputs) { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const workflowInput2 = { test: "payload2" } + + const [{ result: workflowResult }, { result: workflowResult2 }] = + await promiseAll([ + workflow().run({ + input: workflowInput, + }), + workflow().run({ + input: workflowInput2, + }), + ]) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1]).toHaveLength(2) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflowResult2).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose a new workflow with parallelize steps", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + const mockStep4Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 4", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + const step4 = createStep("step4", mockStep4Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const [ret2, ret3] = parallelize(step2(returnStep1), step3(returnStep1)) + return step4({ one: ret2, two: ret3 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep4Fn).toHaveBeenCalledTimes(1) + expect(mockStep4Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep4Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 3", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 3", + }, + }, + ], + obj: "return from 4", + }) + }) + + it("should overwrite existing workflows if the same name is used", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return { inputs: [input], obj: "return from 1" } + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 2", + } + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 3", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const overriddenWorkflow = createWorkflow("workflow1", function (input) { + const ret2 = step2(input) + const returnStep1 = step1(ret2) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await overriddenWorkflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 2", + }) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 2" }], + obj: "return from 1", + }, + two: { inputs: [{ test: "payload1" }], obj: "return from 2" }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 2" }, + ], + obj: "return from 1", + }, + two: { inputs: [{ test: "payload1" }], obj: "return from 2" }, + }, + ], + obj: "return from 3", + }) + }) + + it("should transform the values before forward them to the next step", async () => { + const mockStep1Fn = jest.fn().mockImplementation((obj, context) => { + const ret = { + property: "property", + } + return ret + }) + + const mockStep2Fn = jest.fn().mockImplementation((obj, context) => { + const ret = { + ...obj, + sum: "sum = " + obj.sum, + } + + return ret + }) + + const mockStep3Fn = jest.fn().mockImplementation((param, context) => { + const ret = { + avg: "avg = " + param.avg, + ...param, + } + return ret + }) + + const transform1Fn = jest + .fn() + .mockImplementation(({ input, step1Result }) => { + const newObj = { + ...step1Result, + ...input, + sum: input.a + input.b, + } + return { + input: newObj, + } + }) + + const transform2Fn = jest + .fn() + .mockImplementation(async ({ input }, context) => { + input.another_prop = "another_prop" + return input + }) + + const transform3Fn = jest.fn().mockImplementation(({ obj }) => { + obj.avg = (obj.a + obj.b) / 2 + + return obj + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const mainFlow = createWorkflow("test_", function (input) { + const step1Result = step1(input) + + const sum = transform( + { input, step1Result }, + transform1Fn, + transform2Fn + ) + + const ret2 = step2(sum) + + const avg = transform({ obj: ret2 }, transform3Fn) + + return step3(avg) + }) + + const workflowInput = { a: 1, b: 2 } + await mainFlow().run({ input: workflowInput }) + + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + property: "property", + a: 1, + b: 2, + sum: 3, + another_prop: "another_prop", + }) + + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + sum: "sum = 3", + property: "property", + a: 1, + b: 2, + another_prop: "another_prop", + avg: 1.5, + }) + + expect(transform1Fn).toHaveBeenCalledTimes(1) + expect(transform2Fn).toHaveBeenCalledTimes(1) + expect(transform3Fn).toHaveBeenCalledTimes(1) + }) + + it("should compose a new workflow and access properties from steps", async () => { + const mockStep1Fn = jest.fn().mockImplementation(({ input }, context) => { + return { id: input, product: "product_1", variant: "variant_2" } + }) + const mockStep2Fn = jest.fn().mockImplementation(({ product }) => { + return { + product: "Saved product - " + product, + } + }) + const mockStep3Fn = jest.fn().mockImplementation(({ variant }) => { + return { + variant: "Saved variant - " + variant, + } + }) + + const getData = createStep("step1", mockStep1Fn) + const saveProduct = createStep("step2", mockStep2Fn) + const saveVariant = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const data: any = getData(input) + parallelize( + saveProduct({ product: data.product }), + saveVariant({ variant: data.variant }) + ) + }) + + const workflowInput = "id_123" + await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ product: "product_1" }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ variant: "variant_2" }) + }) + + it("should compose a new workflow exposing hooks and log warns if multiple handlers are registered for the same hook", async () => { + const warn = jest.spyOn(console, "warn").mockImplementation(() => {}) + + const mockStep1Fn = jest.fn().mockImplementation(({ input }) => { + return { id: input, product: "product_1", variant: "variant_2" } + }) + + const mockStep2Fn = jest.fn().mockImplementation(({ product }) => { + product.product = "Saved product - " + product.product + return product + }) + + const getData = createStep("step1", mockStep1Fn) + const saveProduct = createStep("step2", mockStep2Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const data = getData({ input }) + + const hookReturn = hook("changeProduct", { + opinionatedPropertyName: data, + }) + const transformedData = transform( + { data, hookReturn }, + ({ data, hookReturn }: { data: any; hookReturn: any }) => { + return { + ...data, + ...hookReturn, + } + } + ) + + return saveProduct({ product: transformedData }) + }) + + workflow.changeProduct(({ opinionatedPropertyName }) => { + return { + newProperties: "new properties", + prod: opinionatedPropertyName.product + "**", + var: opinionatedPropertyName.variant + "**", + other: [1, 2, 3], + nested: { + a: { + b: "c", + }, + }, + moreProperties: "more properties", + } + }) + + workflow.changeProduct((theReturnOfThePreviousHook) => { + return { + ...theReturnOfThePreviousHook, + moreProperties: "2nd hook update", + } + }) + + const workflowInput = "id_123" + const { result: final } = await workflow().run({ + input: workflowInput, + }) + + expect(warn).toHaveBeenCalledTimes(1) + expect(final).toEqual({ + id: "id_123", + prod: "product_1**", + var: "variant_2**", + variant: "variant_2", + product: "Saved product - product_1", + newProperties: "new properties", + other: [1, 2, 3], + nested: { + a: { + b: "c", + }, + }, + moreProperties: "more properties", + }) + }) + }) + + describe("Using steps returning StepResponse", function () { + afterEach(async () => { + jest.clearAllMocks() + }) + + it("should compose a new workflow and execute it", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [workflowInput], + obj: "return from 1", + }, + two: { + inputs: [ + { + inputs: [workflowInput], + obj: "return from 1", + }, + ], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [workflowInput], + obj: "return from 1", + }, + two: { + inputs: [ + { + inputs: [workflowInput], + obj: "return from 1", + }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows sequentially and execute them sequentially", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflow2 = createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + const workflow2Input = { test: "payload2" } + const { result: workflow2Result } = await workflow2().run({ + input: workflow2Input, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [{ test: "payload1" }], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [{ test: "payload2" }], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows concurrently and execute them sequentially", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const [workflow, workflow2] = await promiseAll([ + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + + createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + ]) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + const workflow2Input = { test: "payload2" } + const { result: workflow2Result } = await workflow2().run({ + input: workflow2Input, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [workflow2Input], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose two new workflows concurrently and execute them concurrently", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const [workflow, workflow2] = await promiseAll([ + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + + createWorkflow("workflow2", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }), + ]) + + const workflowInput = { test: "payload1" } + const workflow2Input = { test: "payload2" } + + const [{ result: workflowResult }, { result: workflow2Result }] = + await promiseAll([ + workflow().run({ + input: workflowInput, + }), + workflow2().run({ + input: workflow2Input, + }), + ]) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1][0]).toEqual(workflow2Input) + expect(mockStep1Fn.mock.calls[1]).toHaveLength(2) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + expect(mockStep2Fn.mock.calls[1][0]).toEqual({ + inputs: [workflow2Input], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + expect(mockStep3Fn.mock.calls[1][0]).toEqual({ + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload2" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflow2Result).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose a new workflow and execute it multiple times concurrently", async () => { + const mockStep1Fn = jest + .fn() + .mockImplementation(function (input, context) { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation(function (...inputs) { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation(function (...inputs) { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const workflowInput2 = { test: "payload2" } + + const [{ result: workflowResult }, { result: workflowResult2 }] = + await promiseAll([ + workflow().run({ + input: workflowInput, + }), + workflow().run({ + input: workflowInput2, + }), + ]) + + expect(mockStep1Fn).toHaveBeenCalledTimes(2) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockStep1Fn.mock.calls[1]).toHaveLength(2) + + expect(mockStep2Fn).toHaveBeenCalledTimes(2) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(2) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload1" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + expect(workflowResult2).toEqual({ + inputs: [ + { + one: { inputs: [{ test: "payload2" }], obj: "return from 1" }, + two: { + inputs: [ + { inputs: [{ test: "payload2" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + }, + ], + obj: "return from 3", + }) + }) + + it("should compose a new workflow with parallelize steps", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + const mockStep4Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return { + inputs, + obj: "return from 4", + } + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + const step4 = createStep("step4", mockStep4Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const [ret2, ret3] = parallelize(step2(returnStep1), step3(returnStep1)) + return step4({ one: ret2, two: ret3 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 1", + }) + + expect(mockStep4Fn).toHaveBeenCalledTimes(1) + expect(mockStep4Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep4Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 2", + }, + two: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 1" }], + obj: "return from 3", + }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 2", + }, + two: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 1" }, + ], + obj: "return from 3", + }, + }, + ], + obj: "return from 4", + }) + }) + + it("should overwrite existing workflows if the same name is used", async () => { + const mockStep1Fn = jest.fn().mockImplementation((input, context) => { + return new StepResponse({ inputs: [input], obj: "return from 1" }) + }) + const mockStep2Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 2", + }) + }) + const mockStep3Fn = jest.fn().mockImplementation((...inputs) => { + const context = inputs.pop() + return new StepResponse({ + inputs, + obj: "return from 3", + }) + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + createWorkflow("workflow1", function (input) { + const returnStep1 = step1(input) + const ret2 = step2(returnStep1) + return step3({ one: returnStep1, two: ret2 }) + }) + + const overriddenWorkflow = createWorkflow("workflow1", function (input) { + const ret2 = step2(input) + const returnStep1 = step1(ret2) + return step3({ one: returnStep1, two: ret2 }) + }) + + const workflowInput = { test: "payload1" } + const { result: workflowResult } = await overriddenWorkflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual({ + inputs: [workflowInput], + obj: "return from 2", + }) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + one: { + inputs: [{ inputs: [{ test: "payload1" }], obj: "return from 2" }], + obj: "return from 1", + }, + two: { inputs: [{ test: "payload1" }], obj: "return from 2" }, + }) + + expect(workflowResult).toEqual({ + inputs: [ + { + one: { + inputs: [ + { inputs: [{ test: "payload1" }], obj: "return from 2" }, + ], + obj: "return from 1", + }, + two: { inputs: [{ test: "payload1" }], obj: "return from 2" }, + }, + ], + obj: "return from 3", + }) + }) + + it("should transform the values before forward them to the next step", async () => { + const mockStep1Fn = jest.fn().mockImplementation((obj, context) => { + const ret = new StepResponse({ + property: "property", + }) + return ret + }) + + const mockStep2Fn = jest.fn().mockImplementation((obj, context) => { + const ret = new StepResponse({ + ...obj, + sum: "sum = " + obj.sum, + }) + + return ret + }) + + const mockStep3Fn = jest.fn().mockImplementation((param, context) => { + const ret = new StepResponse({ + avg: "avg = " + param.avg, + ...param, + }) + return ret + }) + + const transform1Fn = jest + .fn() + .mockImplementation(({ input, step1Result }) => { + const newObj = { + ...step1Result, + ...input, + sum: input.a + input.b, + } + return { + input: newObj, + } + }) + + const transform2Fn = jest + .fn() + .mockImplementation(async ({ input }, context) => { + input.another_prop = "another_prop" + return input + }) + + const transform3Fn = jest.fn().mockImplementation(({ obj }) => { + obj.avg = (obj.a + obj.b) / 2 + + return obj + }) + + const step1 = createStep("step1", mockStep1Fn) + const step2 = createStep("step2", mockStep2Fn) + const step3 = createStep("step3", mockStep3Fn) + + const mainFlow = createWorkflow("test_", function (input) { + const step1Result = step1(input) + + const sum = transform( + { input, step1Result }, + transform1Fn, + transform2Fn + ) + + const ret2 = step2(sum) + + const avg = transform({ obj: ret2 }, transform3Fn) + + return step3(avg) + }) + + const workflowInput = { a: 1, b: 2 } + await mainFlow().run({ input: workflowInput }) + + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ + property: "property", + a: 1, + b: 2, + sum: 3, + another_prop: "another_prop", + }) + + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ + sum: "sum = 3", + property: "property", + a: 1, + b: 2, + another_prop: "another_prop", + avg: 1.5, + }) + + expect(transform1Fn).toHaveBeenCalledTimes(1) + expect(transform2Fn).toHaveBeenCalledTimes(1) + expect(transform3Fn).toHaveBeenCalledTimes(1) + }) + + it("should compose a new workflow and access properties from steps", async () => { + const mockStep1Fn = jest.fn().mockImplementation(({ input }, context) => { + return new StepResponse({ + id: input, + product: "product_1", + variant: "variant_2", + }) + }) + const mockStep2Fn = jest.fn().mockImplementation(({ product }) => { + return new StepResponse({ + product: "Saved product - " + product, + }) + }) + const mockStep3Fn = jest.fn().mockImplementation(({ variant }) => { + return new StepResponse({ + variant: "Saved variant - " + variant, + }) + }) + + const getData = createStep("step1", mockStep1Fn) + const saveProduct = createStep("step2", mockStep2Fn) + const saveVariant = createStep("step3", mockStep3Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const data: any = getData(input) + parallelize( + saveProduct({ product: data.product }), + saveVariant({ variant: data.variant }) + ) + }) + + const workflowInput = "id_123" + await workflow().run({ + input: workflowInput, + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockStep1Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + + expect(mockStep2Fn).toHaveBeenCalledTimes(1) + expect(mockStep2Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep2Fn.mock.calls[0][0]).toEqual({ product: "product_1" }) + + expect(mockStep3Fn).toHaveBeenCalledTimes(1) + expect(mockStep3Fn.mock.calls[0]).toHaveLength(2) + expect(mockStep3Fn.mock.calls[0][0]).toEqual({ variant: "variant_2" }) + }) + + it("should compose a new workflow exposing hooks and log warns if multiple handlers are registered for the same hook", async () => { + const warn = jest.spyOn(console, "warn").mockImplementation(() => {}) + + const mockStep1Fn = jest.fn().mockImplementation(({ input }) => { + return new StepResponse({ + id: input, + product: "product_1", + variant: "variant_2", + }) + }) + + const mockStep2Fn = jest.fn().mockImplementation(({ product }) => { + product.product = "Saved product - " + product.product + return new StepResponse(product) + }) + + const getData = createStep("step1", mockStep1Fn) + const saveProduct = createStep("step2", mockStep2Fn) + + const workflow = createWorkflow("workflow1", function (input) { + const data = getData({ input }) + + const hookReturn = hook("changeProduct", { + opinionatedPropertyName: data, + }) + const transformedData = transform( + { data, hookReturn }, + ({ data, hookReturn }: { data: any; hookReturn: any }) => { + return { + ...data, + ...hookReturn, + } + } + ) + + return saveProduct({ product: transformedData }) + }) + + workflow.changeProduct(({ opinionatedPropertyName }) => { + return { + newProperties: "new properties", + prod: opinionatedPropertyName.product + "**", + var: opinionatedPropertyName.variant + "**", + other: [1, 2, 3], + nested: { + a: { + b: "c", + }, + }, + moreProperties: "more properties", + } + }) + + workflow.changeProduct((theReturnOfThePreviousHook) => { + return { + ...theReturnOfThePreviousHook, + moreProperties: "2nd hook update", + } + }) + + const workflowInput = "id_123" + const { result: final } = await workflow().run({ + input: workflowInput, + }) + + expect(warn).toHaveBeenCalledTimes(1) + expect(final).toEqual({ + id: "id_123", + prod: "product_1**", + var: "variant_2**", + variant: "variant_2", + product: "Saved product - product_1", + newProperties: "new properties", + other: [1, 2, 3], + nested: { + a: { + b: "c", + }, + }, + moreProperties: "more properties", + }) + }) + }) + + it("should compose a workflow that throws without crashing and the compensation will receive undefined for the step that fails", async () => { + const mockStep1Fn = jest.fn().mockImplementation(function (input) { + throw new Error("invoke fail") + }) + + const mockCompensateSte1 = jest.fn().mockImplementation(function (input) { + return input + }) + + const step1 = createStep("step1", mockStep1Fn, mockCompensateSte1) + + const workflow = createWorkflow("workflow1", function (input) { + return step1(input) + }) + + const workflowInput = { test: "payload1" } + const { errors } = await workflow().run({ + input: workflowInput, + throwOnError: false, + }) + + expect(errors).toHaveLength(1) + expect(errors[0]).toEqual({ + action: "step1", + handlerType: "invoke", + error: expect.objectContaining({ + message: "invoke fail", + }), + }) + + expect(mockStep1Fn).toHaveBeenCalledTimes(1) + expect(mockCompensateSte1).toHaveBeenCalledTimes(1) + + expect(mockStep1Fn.mock.calls[0][0]).toEqual(workflowInput) + expect(mockCompensateSte1.mock.calls[0][0]).toEqual(undefined) + }) +}) diff --git a/integration-tests/plugins/helpers/create-default-rule-types.ts b/integration-tests/plugins/helpers/create-default-rule-types.ts index e063d642bb78c..6db9fb25ef3e4 100644 --- a/integration-tests/plugins/helpers/create-default-rule-types.ts +++ b/integration-tests/plugins/helpers/create-default-rule-types.ts @@ -10,5 +10,9 @@ export const createDefaultRuleTypes = async (container) => { name: "region_id", rule_attribute: "region_id", }, + { + name: "customer_group_id", + rule_attribute: "customer_group_id", + }, ]) } diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index e3c07aa393c05..35a2ab67ecce5 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --detectOpenHandles --logHeapUsage --clearMocks --no-compilation-cache --forceExit", + "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --detectOpenHandles --logHeapUsage --clearMocks --forceExit", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { diff --git a/packages/admin-ui/ui/src/components/forms/general/prices-form/index.tsx b/packages/admin-ui/ui/src/components/forms/general/prices-form/index.tsx deleted file mode 100644 index c89b4bc55d028..0000000000000 --- a/packages/admin-ui/ui/src/components/forms/general/prices-form/index.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { useAdminRegions, useAdminStore } from "medusa-react" -import { useEffect, useMemo } from "react" -import { FieldArrayWithId, useFieldArray } from "react-hook-form" -import { NestedForm } from "../../../../utils/nested-form" -import NestedPrice from "./nested-price" - -type PricePayload = { - id: string | null - amount: number | null - currency_code: string - region_id: string | null - includes_tax?: boolean -} - -type PriceObject = FieldArrayWithId< - { - __nested__: PricesFormType - }, - "__nested__.prices", - "id" -> & { index: number } - -export type PricesFormType = { - prices: PricePayload[] -} - -export type NestedPriceObject = { - currencyPrice: PriceObject - regionPrices: (PriceObject & { regionName: string })[] -} - -type Props = { - form: NestedForm - required?: boolean -} - -/** - * Re-usable nested form used to submit pricing information for products and their variants. - * Fetches store currencies and regions from the backend, and allows the user to specify both - * currency and region specific prices. - * @example - * - */ -const PricesForm = ({ form }: Props) => { - const { store } = useAdminStore() - const { regions } = useAdminRegions() - - const { control, path } = form - - const { append, update, fields } = useFieldArray({ - control, - name: path("prices"), - }) - - useEffect(() => { - if (!regions || !store || !fields) { - return - } - - regions.forEach((reg) => { - if (!fields.some((field) => field.region_id === reg.id)) { - append({ - id: null, - region_id: reg.id, - amount: null, - currency_code: reg.currency_code, - includes_tax: reg.includes_tax, - }) - } - }) - - store.currencies.forEach((cur) => { - if (!fields.some((field) => field.currency_code === cur.code)) { - append({ - id: null, - currency_code: cur.code, - amount: null, - region_id: null, - includes_tax: cur.includes_tax, - }) - } - }) - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [regions, store, fields]) - - // Ensure that prices are up to date with their respective tax inclusion setting - useEffect(() => { - if (!regions || !fields || !store) { - return - } - - regions.forEach((reg) => { - const regionPrice = fields.findIndex( - (field) => !!field && field.region_id === reg.id - ) - - if ( - regionPrice !== -1 && - fields[regionPrice].includes_tax !== reg.includes_tax - ) { - update(regionPrice, { - ...fields[regionPrice], - includes_tax: reg.includes_tax, - }) - } - }) - - store.currencies.forEach((cur) => { - const currencyPrice = fields.findIndex( - (field) => - !!field && !field.region_id && field.currency_code === cur.code - ) - - if ( - currencyPrice !== -1 && - fields[currencyPrice].includes_tax !== cur.includes_tax - ) { - update(currencyPrice, { - ...fields[currencyPrice], - includes_tax: cur.includes_tax, - }) - } - }) - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [regions, store]) - - const priceObj = useMemo(() => { - const obj: Record = {} - - const currencyPrices = fields.filter((field) => field.region_id === null) - const regionPrices = fields.filter((field) => field.region_id !== null) - - currencyPrices.forEach((price) => { - obj[price.currency_code!] = { - currencyPrice: { - ...price, - index: fields.indexOf(price), - }, - regionPrices: regionPrices - .filter( - (regionPrice) => regionPrice.currency_code === price.currency_code - ) - .map((rp) => ({ - ...rp, - regionName: regions?.find((r) => r.id === rp.region_id)?.name || "", - index: fields.indexOf(rp), - })), - } - }) - - return obj - }, [fields, regions]) - - return ( -
-
- {Object.values(priceObj).map((po) => { - return ( - - ) - })} -
-
- ) -} - -export default PricesForm diff --git a/packages/admin-ui/ui/src/components/forms/general/prices-form/nested-price.tsx b/packages/admin-ui/ui/src/components/forms/general/prices-form/nested-price.tsx deleted file mode 100644 index 8a073b5abd52c..0000000000000 --- a/packages/admin-ui/ui/src/components/forms/general/prices-form/nested-price.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { NestedPriceObject, PricesFormType } from "." - -import CoinsIcon from "../../../fundamentals/icons/coins-icon" -import { Controller } from "react-hook-form" -import IncludesTaxTooltip from "../../../atoms/includes-tax-tooltip" -import MapPinIcon from "../../../fundamentals/icons/map-pin-icon" -import { NestedForm } from "../../../../utils/nested-form" -import PriceFormInput from "./price-form-input" -import TriangleRightIcon from "../../../fundamentals/icons/triangle-right-icon" -import clsx from "clsx" -import { currencies } from "../../../../utils/currencies" -import useToggleState from "../../../../hooks/use-toggle-state" - -type Props = { - form: NestedForm - nestedPrice: NestedPriceObject -} - -const NestedPrice = ({ form, nestedPrice }: Props) => { - const { state, toggle } = useToggleState() - - const { control, path } = form - const { currencyPrice, regionPrices } = nestedPrice - return ( -
-
- -
-
- -
-
- - {currencyPrice.currency_code.toUpperCase()} - - - {currencies[currencyPrice.currency_code.toUpperCase()].name} - - -
-
- { - return ( - - ) - }} - /> -
-
    - {regionPrices.map((rp) => { - return ( -
    -
    -
    - -
    -
    - - {rp.regionName} - - -
    -
    - { - return ( - - ) - }} - /> -
    - ) - })} -
-
- ) -} - -export default NestedPrice diff --git a/packages/admin-ui/ui/src/components/forms/product/variant-form/create-flow-variant-form/index.tsx b/packages/admin-ui/ui/src/components/forms/product/variant-form/create-flow-variant-form/index.tsx index c4a758ae8f791..1ac5bfd99e9cf 100644 --- a/packages/admin-ui/ui/src/components/forms/product/variant-form/create-flow-variant-form/index.tsx +++ b/packages/admin-ui/ui/src/components/forms/product/variant-form/create-flow-variant-form/index.tsx @@ -1,28 +1,26 @@ -import { UseFormReturn } from "react-hook-form" -import { nestedForm } from "../../../../../utils/nested-form" -import InputError from "../../../../atoms/input-error" -import IconTooltip from "../../../../molecules/icon-tooltip" -import Accordion from "../../../../organisms/accordion" -import { PricesFormType } from "../../../general/prices-form" import CustomsForm, { CustomsFormType } from "../../customs-form" import DimensionsForm, { DimensionsFormType } from "../../dimensions-form" import VariantGeneralForm, { VariantGeneralFormType, } from "../variant-general-form" -import VariantPricesForm from "../variant-prices-form" import VariantSelectOptionsForm, { VariantOptionValueType, VariantSelectOptionsFormType, } from "../variant-select-options-form" import VariantStockForm, { VariantStockFormType } from "../variant-stock-form" +import Accordion from "../../../../organisms/accordion" +import IconTooltip from "../../../../molecules/icon-tooltip" +import InputError from "../../../../atoms/input-error" +import { UseFormReturn } from "react-hook-form" +import { nestedForm } from "../../../../../utils/nested-form" + export type CreateFlowVariantFormType = { /** * Used to identify the variant during product create flow. Will not be submitted to the backend. */ _internal_id?: string general: VariantGeneralFormType - prices: PricesFormType stock: VariantStockFormType options: VariantSelectOptionsFormType customs: CustomsFormType @@ -77,9 +75,6 @@ const CreateFlowVariantForm = ({ form, options, onCreateOption }: Props) => { - - - diff --git a/packages/admin-ui/ui/src/components/forms/product/variant-form/edit-flow-variant-form/index.tsx b/packages/admin-ui/ui/src/components/forms/product/variant-form/edit-flow-variant-form/index.tsx index 1059aa5e31e92..9ab784d243bf3 100644 --- a/packages/admin-ui/ui/src/components/forms/product/variant-form/edit-flow-variant-form/index.tsx +++ b/packages/admin-ui/ui/src/components/forms/product/variant-form/edit-flow-variant-form/index.tsx @@ -1,19 +1,18 @@ -import { useFieldArray, UseFormReturn } from "react-hook-form" import CustomsForm, { CustomsFormType } from "../../customs-form" import DimensionsForm, { DimensionsFormType } from "../../dimensions-form" +import MetadataForm, { MetadataFormType } from "../../../general/metadata-form" +import { UseFormReturn, useFieldArray } from "react-hook-form" import VariantGeneralForm, { VariantGeneralFormType, } from "../variant-general-form" import VariantStockForm, { VariantStockFormType } from "../variant-stock-form" -import { useFeatureFlag } from "../../../../../providers/feature-flag-provider" -import { nestedForm } from "../../../../../utils/nested-form" +import Accordion from "../../../../organisms/accordion" import IconTooltip from "../../../../molecules/icon-tooltip" import InputField from "../../../../molecules/input" -import Accordion from "../../../../organisms/accordion" -import MetadataForm, { MetadataFormType } from "../../../general/metadata-form" import { PricesFormType } from "../../../general/prices-form" -import VariantPricesForm from "../variant-prices-form" +import { nestedForm } from "../../../../../utils/nested-form" +import { useFeatureFlag } from "../../../../../providers/feature-flag-provider" export type EditFlowVariantFormType = { /** @@ -97,9 +96,6 @@ const EditFlowVariantForm = ({ form, isEdit }: Props) => { - - - {showStockAndInventory && ( diff --git a/packages/admin-ui/ui/src/components/forms/product/variant-form/variant-prices-form/index.tsx b/packages/admin-ui/ui/src/components/forms/product/variant-form/variant-prices-form/index.tsx deleted file mode 100644 index 87a558c6a1b31..0000000000000 --- a/packages/admin-ui/ui/src/components/forms/product/variant-form/variant-prices-form/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { NestedForm } from "../../../../../utils/nested-form" -import PricesForm, { PricesFormType } from "../../../general/prices-form" - -type Props = { - form: NestedForm -} - -const VariantPricesForm = ({ form }: Props) => { - return ( -
-

- Configure the pricing for this variant. -

-
- -
-
- ) -} - -export default VariantPricesForm diff --git a/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-prices-modal/index.tsx b/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-prices-modal/index.tsx index 1ce14aab7e19c..1879a88e2c3d3 100644 --- a/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-prices-modal/index.tsx +++ b/packages/admin-ui/ui/src/components/organisms/product-variants-section/edit-prices-modal/index.tsx @@ -1,27 +1,26 @@ import { MoneyAmount, Product } from "@medusajs/client-types" -import mapKeys from "lodash/mapKeys" -import pick from "lodash/pick" -import pickBy from "lodash/pickBy" +import { + getAllProductPricesCurrencies, + getAllProductPricesRegions, + getCurrencyPricesOnly, + getRegionPricesOnly, +} from "./utils" import { useAdminRegions, useAdminUpdateVariant } from "medusa-react" import { useEffect, useMemo, useRef, useState } from "react" -import { currencies as CURRENCY_MAP } from "../../../../utils/currencies" - -import useNotification from "../../../../hooks/use-notification" -import Fade from "../../../atoms/fade-wrapper" import Button from "../../../fundamentals/button" +import { currencies as CURRENCY_MAP } from "../../../../utils/currencies" import CrossIcon from "../../../fundamentals/icons/cross-icon" -import Modal from "../../../molecules/modal" import DeletePrompt from "../../delete-prompt" import EditPricesActions from "./edit-prices-actions" import EditPricesTable from "./edit-prices-table" +import Fade from "../../../atoms/fade-wrapper" +import Modal from "../../../molecules/modal" import SavePrompt from "./save-prompt" -import { - getAllProductPricesCurrencies, - getAllProductPricesRegions, - getCurrencyPricesOnly, - getRegionPricesOnly, -} from "./utils" +import mapKeys from "lodash/mapKeys" +import pick from "lodash/pick" +import pickBy from "lodash/pickBy" +import useNotification from "../../../../hooks/use-notification" type EditPricesModalProps = { close: () => void diff --git a/packages/design-system/ui/src/components/code-block/code-block.tsx b/packages/design-system/ui/src/components/code-block/code-block.tsx index b617159822be0..8371c15487b96 100644 --- a/packages/design-system/ui/src/components/code-block/code-block.tsx +++ b/packages/design-system/ui/src/components/code-block/code-block.tsx @@ -138,22 +138,62 @@ const Body = ({ ...themes.palenight, plain: { color: "rgba(249, 250, 251, 1)", - backgroundColor: "#111827", + backgroundColor: "rgb(17,24,39)", }, styles: [ + ...themes.palenight.styles, { types: ["keyword"], style: { - color: "var(--fg-on-color)", + fontStyle: "normal", + color: "rgb(187,160,255)", + }, + }, + { + types: ["punctuation", "operator"], + style: { + fontStyle: "normal", + color: "rgb(255,255,255)", + }, + }, + { + types: ["constant", "boolean"], + style: { + fontStyle: "normal", + color: "rgb(187,77,96)", + }, + }, + { + types: ["function"], + style: { + fontStyle: "normal", + color: "rgb(27,198,242)", + }, + }, + { + types: ["number"], + style: { + color: "rgb(247,208,25)", }, }, { types: ["maybe-class-name"], style: { - color: "rgb(255, 203, 107)", + color: "rgb(255,203,107)", + }, + }, + { + types: ["string"], + style: { + color: "rgb(73,209,110)", + }, + }, + { + types: ["comment"], + style: { + color: "rgb(52,211,153)", }, }, - ...themes.palenight.styles, ], }} code={active.code} diff --git a/packages/link-modules/src/index.ts b/packages/link-modules/src/index.ts index 3acb2f2c61577..4bbfce7a57d4d 100644 --- a/packages/link-modules/src/index.ts +++ b/packages/link-modules/src/index.ts @@ -2,3 +2,4 @@ export * from "./initialize" export * from "./types" export * from "./loaders" export * from "./services" +export * from "./utils/compose-link-name" diff --git a/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts b/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts index 64bd889064e14..7e2b51109dc1e 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts @@ -1,12 +1,15 @@ +import { MedusaV2Flag } from "@medusajs/utils" +import { updatePriceLists } from "@medusajs/workflows" +import { Type } from "class-transformer" import { IsArray, IsBoolean, IsOptional, ValidateNested } from "class-validator" +import { EntityManager } from "typeorm" import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "." - -import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list" import { PriceList } from "../../../.." import PriceListService from "../../../../services/price-list" -import { Type } from "class-transformer" +import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list" import { validator } from "../../../../utils/validator" -import { EntityManager } from "typeorm" +import { MedusaContainer } from "@medusajs/types" +import { getPriceListPricingModule } from "./modules-queries" /** * @oas [post] /admin/price-lists/{id}/prices/batch @@ -85,23 +88,48 @@ import { EntityManager } from "typeorm" */ export default async (req, res) => { const { id } = req.params + let priceList + const featureFlagRouter = req.scope.resolve("featureFlagRouter") + const manager: EntityManager = req.scope.resolve("manager") + const priceListService: PriceListService = + req.scope.resolve("priceListService") const validated = await validator(AdminPostPriceListPricesPricesReq, req.body) - const priceListService: PriceListService = - req.scope.resolve("priceListService") + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + const updatePriceListWorkflow = updatePriceLists(req.scope) - const manager: EntityManager = req.scope.resolve("manager") - await manager.transaction(async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .addPrices(id, validated.prices, validated.override) - }) + const input = { + price_lists: [ + { + id, + ...validated, + }, + ], + } + + await updatePriceListWorkflow.run({ + input, + context: { + manager, + }, + }) + + priceList = await getPriceListPricingModule(id, { + container: req.scope as MedusaContainer, + }) + } else { + await manager.transaction(async (transactionManager) => { + await priceListService + .withTransaction(transactionManager) + .addPrices(id, validated.prices, validated.override) + }) - const priceList = await priceListService.retrieve(id, { - select: defaultAdminPriceListFields as (keyof PriceList)[], - relations: defaultAdminPriceListRelations, - }) + priceList = await priceListService.retrieve(id, { + select: defaultAdminPriceListFields as (keyof PriceList)[], + relations: defaultAdminPriceListRelations, + }) + } res.json({ price_list: priceList }) } diff --git a/packages/medusa/src/api/routes/admin/price-lists/create-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/create-price-list.ts index fc9fc6e7126e3..1d1cbaf1d9271 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/create-price-list.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/create-price-list.ts @@ -1,3 +1,12 @@ +import { MedusaContainer, PricingTypes, WorkflowTypes } from "@medusajs/types" +import { + FlagRouter, + MedusaV2Flag, + PriceListStatus, + PriceListType, +} from "@medusajs/utils" +import { createPriceLists } from "@medusajs/workflows" +import { Type } from "class-transformer" import { IsArray, IsBoolean, @@ -6,23 +15,18 @@ import { IsString, ValidateNested, } from "class-validator" -import { - AdminPriceListPricesCreateReq, - CreatePriceListInput, -} from "../../../../types/price-list" - -import { PriceListStatus, PriceListType } from "@medusajs/utils" -import { Type } from "class-transformer" import { Request } from "express" import { EntityManager } from "typeorm" +import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "." import TaxInclusivePricingFeatureFlag from "../../../../loaders/feature-flags/tax-inclusive-pricing" import { PriceList } from "../../../../models" import PriceListService from "../../../../services/price-list" -import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators" import { - defaultAdminPriceListFields, - defaultAdminPriceListRelations, -} from "./index" + AdminPriceListPricesCreateReq, + CreatePriceListInput, +} from "../../../../types/price-list" +import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators" +import { getPriceListPricingModule } from "./modules-queries" /** * @oas [post] /admin/price-lists @@ -109,16 +113,57 @@ export default async (req: Request, res) => { req.scope.resolve("priceListService") const manager: EntityManager = req.scope.resolve("manager") - let priceList = await manager.transaction(async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .create(req.validatedBody as CreatePriceListInput) - }) - - priceList = await priceListService.retrieve(priceList.id, { - select: defaultAdminPriceListFields as (keyof PriceList)[], - relations: defaultAdminPriceListRelations, - }) + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") + let priceList + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key + ) + + if (isMedusaV2FlagEnabled) { + const createPriceListWorkflow = createPriceLists(req.scope) + const validatedInput = req.validatedBody as CreatePriceListInput + const rules: PricingTypes.CreatePriceListRules = {} + const customerGroups = validatedInput?.customer_groups || [] + delete validatedInput.customer_groups + + if (customerGroups.length) { + rules["customer_group_id"] = customerGroups.map((cg) => cg.id) + } + + const input = { + price_lists: [ + { + ...validatedInput, + rules, + }, + ], + } as WorkflowTypes.PriceListWorkflow.CreatePriceListWorkflowInputDTO + + const { result } = await createPriceListWorkflow.run({ + input, + context: { + manager, + }, + }) + + priceList = result[0]!.priceList + + priceList = await getPriceListPricingModule(priceList.id, { + container: req.scope as MedusaContainer, + }) + } else { + priceList = await manager.transaction(async (transactionManager) => { + return await priceListService + .withTransaction(transactionManager) + .create(req.validatedBody as CreatePriceListInput) + }) + + priceList = await priceListService.retrieve(priceList.id, { + select: defaultAdminPriceListFields as (keyof PriceList)[], + relations: defaultAdminPriceListRelations, + }) + } res.json({ price_list: priceList }) } diff --git a/packages/medusa/src/api/routes/admin/price-lists/delete-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/delete-price-list.ts index 54af5cfaafe6c..94db28f0d6772 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/delete-price-list.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/delete-price-list.ts @@ -1,3 +1,6 @@ +import { WorkflowTypes } from "@medusajs/types" +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { removePriceLists } from "@medusajs/workflows" import { EntityManager } from "typeorm" import PriceListService from "../../../../services/price-list" @@ -56,12 +59,33 @@ import PriceListService from "../../../../services/price-list" export default async (req, res) => { const { id } = req.params - const priceListService: PriceListService = - req.scope.resolve("priceListService") + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") - await manager.transaction(async (transactionManager) => { - return await priceListService.withTransaction(transactionManager).delete(id) - }) + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key + ) + + if (isMedusaV2FlagEnabled) { + const removePriceListsWorkflow = removePriceLists(req.scope) + + const input = { + price_lists: [id], + } as WorkflowTypes.PriceListWorkflow.RemovePriceListWorkflowInputDTO + + await removePriceListsWorkflow.run({ + input, + context: { + manager, + }, + }) + } else { + const priceListService: PriceListService = + req.scope.resolve("priceListService") + await manager.transaction(async (transactionManager) => { + await priceListService.withTransaction(transactionManager).delete(id) + }) + } res.json({ id, diff --git a/packages/medusa/src/api/routes/admin/price-lists/delete-prices-batch.ts b/packages/medusa/src/api/routes/admin/price-lists/delete-prices-batch.ts index 5de013889f5ff..96fa6f8d09473 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/delete-prices-batch.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/delete-prices-batch.ts @@ -1,8 +1,10 @@ +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { removePriceListProductPrices } from "@medusajs/workflows/dist/definition/price-list/remove-price-list-prices" import { ArrayNotEmpty, IsString } from "class-validator" - import { EntityManager } from "typeorm" import PriceListService from "../../../../services/price-list" import { validator } from "../../../../utils/validator" +import { WorkflowTypes } from "@medusajs/types" /** * @oas [delete] /admin/price-lists/{id}/prices/batch @@ -81,13 +83,37 @@ export default async (req, res) => { const priceListService: PriceListService = req.scope.resolve("priceListService") + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") - await manager.transaction(async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .deletePrices(id, validated.price_ids) - }) + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key + ) + + if (isMedusaV2FlagEnabled) { + const deletePriceListPricesWorkflow = removePriceListProductPrices( + req.scope + ) + + const input = { + price_list_id: id, + money_amount_ids: validated.price_ids, + } as WorkflowTypes.PriceListWorkflow.RemovePriceListPricesWorkflowInputDTO + + await deletePriceListPricesWorkflow.run({ + input, + context: { + manager, + }, + }) + } else { + await manager.transaction(async (transactionManager) => { + await priceListService + .withTransaction(transactionManager) + .deletePrices(id, validated.price_ids) + }) + } res.json({ ids: validated.price_ids, object: "money-amount", deleted: true }) } diff --git a/packages/medusa/src/api/routes/admin/price-lists/delete-product-prices.ts b/packages/medusa/src/api/routes/admin/price-lists/delete-product-prices.ts index 6c424c9624cbb..d12de2e6e461f 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/delete-product-prices.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/delete-product-prices.ts @@ -1,3 +1,6 @@ +import { WorkflowTypes } from "@medusajs/types" +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { removePriceListProductPrices } from "@medusajs/workflows/dist/definition/price-list/remove-product-prices" import { EntityManager } from "typeorm" import PriceListService from "../../../../services/price-list" @@ -60,15 +63,44 @@ export default async (req, res) => { const priceListService: PriceListService = req.scope.resolve("priceListService") + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") - const [deletedPriceIds] = await manager.transaction( - async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .deleteProductPrices(id, [product_id]) - } + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key ) + let deletedPriceIds: string[] = [] + + if (isMedusaV2FlagEnabled) { + const deletePriceListProductsWorkflow = removePriceListProductPrices( + req.scope + ) + + const input = { + product_ids: [product_id], + price_list_id: id, + } as WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO + + const { result } = await deletePriceListProductsWorkflow.run({ + input, + context: { + manager, + }, + }) + + deletedPriceIds = result + } else { + const [deletedIds] = await manager.transaction( + async (transactionManager) => { + return await priceListService + .withTransaction(transactionManager) + .deleteProductPrices(id, [product_id]) + } + ) + deletedPriceIds = deletedIds + } + return res.json({ ids: deletedPriceIds, object: "money-amount", diff --git a/packages/medusa/src/api/routes/admin/price-lists/delete-products-prices-batch.ts b/packages/medusa/src/api/routes/admin/price-lists/delete-products-prices-batch.ts index 4209879087187..129a21ccfc74a 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/delete-products-prices-batch.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/delete-products-prices-batch.ts @@ -1,8 +1,11 @@ +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { removePriceListProductPrices } from "@medusajs/workflows" import { ArrayNotEmpty, IsString } from "class-validator" import { Request, Response } from "express" import { EntityManager } from "typeorm" import PriceListService from "../../../../services/price-list" import { validator } from "../../../../utils/validator" +import { WorkflowTypes } from "@medusajs/types" /** * @oas [delete] /admin/price-lists/{id}/products/prices/batch @@ -79,15 +82,44 @@ export default async (req: Request, res: Response) => { const priceListService: PriceListService = req.scope.resolve("priceListService") + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") - const [deletedPriceIds] = await manager.transaction( - async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .deleteProductPrices(id, validated.product_ids) - } + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key ) + let deletedPriceIds: string[] = [] + + if (isMedusaV2FlagEnabled) { + const deletePriceListProductsWorkflow = removePriceListProductPrices( + req.scope + ) + + const input = { + product_ids: validated.product_ids, + price_list_id: id, + } as WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO + + const { result } = await deletePriceListProductsWorkflow.run({ + input, + context: { + manager, + }, + }) + deletedPriceIds = result + } else { + const [deletedIds] = await manager.transaction( + async (transactionManager) => { + return await priceListService + .withTransaction(transactionManager) + .deleteProductPrices(id, validated.product_ids) + } + ) + + deletedPriceIds = deletedIds + } + return res.json({ ids: deletedPriceIds, object: "money-amount", diff --git a/packages/medusa/src/api/routes/admin/price-lists/delete-variant-prices.ts b/packages/medusa/src/api/routes/admin/price-lists/delete-variant-prices.ts index 4ba20c9750146..45a61d643fb3d 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/delete-variant-prices.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/delete-variant-prices.ts @@ -1,5 +1,8 @@ +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { removePriceListVariantPrices } from "@medusajs/workflows" import { EntityManager } from "typeorm" import PriceListService from "../../../../services/price-list" +import { WorkflowTypes } from "@medusajs/types" /** * @oas [delete] /admin/price-lists/{id}/variants/{variant_id}/prices @@ -59,16 +62,44 @@ export default async (req, res) => { const priceListService: PriceListService = req.scope.resolve("priceListService") - + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") - const [deletedPriceIds] = await manager.transaction( - async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .deleteVariantPrices(id, [variant_id]) - } + + const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled( + MedusaV2Flag.key ) + let deletedPriceIds: string[] = [] + + if (isMedusaV2FlagEnabled) { + const deletePriceListProductsWorkflow = removePriceListVariantPrices( + req.scope + ) + + const input = { + variant_ids: [variant_id], + price_list_id: id, + } as WorkflowTypes.PriceListWorkflow.RemovePriceListVariantsWorkflowInputDTO + + const { result } = await deletePriceListProductsWorkflow.run({ + input, + context: { + manager, + }, + }) + deletedPriceIds = result + } else { + const [deletedIds] = await manager.transaction( + async (transactionManager) => { + return await priceListService + .withTransaction(transactionManager) + .deleteVariantPrices(id, [variant_id]) + } + ) + + deletedPriceIds = deletedIds + } + return res.json({ ids: deletedPriceIds, object: "money-amount", diff --git a/packages/medusa/src/api/routes/admin/price-lists/get-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/get-price-list.ts index 0939d06b0d32e..9faa088f55b58 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/get-price-list.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/get-price-list.ts @@ -1,7 +1,9 @@ +import { MedusaContainer } from "@medusajs/types" +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "." - import { PriceList } from "../../../.." import PriceListService from "../../../../services/price-list" +import { getPriceListPricingModule } from "./modules-queries" /** * @oas [get] /admin/price-lists/{id} @@ -58,13 +60,22 @@ import PriceListService from "../../../../services/price-list" export default async (req, res) => { const { id } = req.params + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const priceListService: PriceListService = req.scope.resolve("priceListService") - const priceList = await priceListService.retrieve(id, { - select: defaultAdminPriceListFields as (keyof PriceList)[], - relations: defaultAdminPriceListRelations, - }) + let priceList + + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + priceList = await getPriceListPricingModule(id, { + container: req.scope as MedusaContainer, + }) + } else { + priceList = await priceListService.retrieve(id, { + select: defaultAdminPriceListFields as (keyof PriceList)[], + relations: defaultAdminPriceListRelations, + }) + } res.status(200).json({ price_list: priceList }) } diff --git a/packages/medusa/src/api/routes/admin/price-lists/index.ts b/packages/medusa/src/api/routes/admin/price-lists/index.ts index f4ff52921a4a8..bc324b09a71cd 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/index.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/index.ts @@ -9,6 +9,7 @@ import middlewares, { import { defaultAdminProductFields, defaultAdminProductRelations, + defaultAdminProductRemoteQueryObject, } from "../products" import { FlagRouter } from "@medusajs/utils" @@ -86,6 +87,50 @@ export default (app, featureFlagRouter: FlagRouter) => { return app } +export const defaultAdminPriceListRemoteQueryObject = { + fields: [ + "created_at", + "deleted_at", + "description", + "ends_at", + "id", + "title", + "starts_at", + "status", + "type", + "updated_at", + ], + price_list_rules: { + price_list_rule_values: { + fields: ["value"], + }, + rule_type: { + fields: ["rule_attribute"], + }, + }, + price_set_money_amounts: { + money_amount: { + fields: [ + "id", + "currency_code", + "amount", + "min_quantity", + "max_quantity", + "created_at", + "deleted_at", + "updated_at", + ], + }, + price_set: { + variant_link: { + variant: { + fields: defaultAdminProductRemoteQueryObject.variants.fields, + }, + }, + }, + }, +} + export const defaultAdminPriceListFields = [ "id", "name", diff --git a/packages/medusa/src/api/routes/admin/price-lists/list-price-list-products.ts b/packages/medusa/src/api/routes/admin/price-lists/list-price-list-products.ts index 6fc229b553d21..ec36d3838e90c 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/list-price-list-products.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/list-price-list-products.ts @@ -1,7 +1,3 @@ -import { - DateComparisonOperator, - extendedFindParamsMixin, -} from "../../../../types/common" import { IsArray, IsBoolean, @@ -10,14 +6,20 @@ import { IsString, ValidateNested, } from "class-validator" -import { MedusaError, isDefined } from "medusa-core-utils" +import { isDefined } from "medusa-core-utils" +import { + DateComparisonOperator, + extendedFindParamsMixin, +} from "../../../../types/common" -import { FilterableProductProps } from "../../../../types/product" -import PriceListService from "../../../../services/price-list" -import { ProductStatus } from "../../../../models" -import { Request } from "express" +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" import { Type } from "class-transformer" +import { Request } from "express" import { pickBy } from "lodash" +import { ProductStatus } from "../../../../models" +import PriceListService from "../../../../services/price-list" +import { FilterableProductProps } from "../../../../types/product" +import { listAndCountProductWithIsolatedProductModule } from "../products/list-products" /** * @oas [get] /admin/price-lists/{id}/products @@ -181,6 +183,9 @@ import { pickBy } from "lodash" export default async (req: Request, res) => { const { id } = req.params const { offset, limit } = req.validatedQuery + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") + let products + let count const priceListService: PriceListService = req.scope.resolve("priceListService") @@ -190,11 +195,19 @@ export default async (req: Request, res) => { price_list_id: [id], } - const [products, count] = await priceListService.listProducts( - id, - pickBy(filterableFields, (val) => isDefined(val)), - req.listConfig - ) + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + ;[products, count] = await listAndCountProductWithIsolatedProductModule( + req, + filterableFields, + req.listConfig + ) + } else { + ;[products, count] = await priceListService.listProducts( + id, + pickBy(filterableFields, (val) => isDefined(val)), + req.listConfig + ) + } res.json({ products, diff --git a/packages/medusa/src/api/routes/admin/price-lists/list-price-lists.ts b/packages/medusa/src/api/routes/admin/price-lists/list-price-lists.ts index d868794fb8809..b1d3013cc3a12 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/list-price-lists.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/list-price-lists.ts @@ -1,9 +1,11 @@ +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { Type } from "class-transformer" import { IsNumber, IsOptional, IsString } from "class-validator" - -import { FilterablePriceListProps } from "../../../../types/price-list" -import PriceListService from "../../../../services/price-list" import { Request } from "express" -import { Type } from "class-transformer" +import PriceListService from "../../../../services/price-list" +import { FilterablePriceListProps } from "../../../../types/price-list" +import { MedusaContainer } from "@medusajs/types" +import { listAndCountPriceListPricingModule } from "./modules-queries" /** * @oas [get] /admin/price-lists @@ -161,18 +163,30 @@ import { Type } from "class-transformer" * $ref: "#/components/responses/500_error" */ export default async (req: Request, res) => { + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") + const validated = req.validatedQuery + let priceLists + let count - const priceListService: PriceListService = - req.scope.resolve("priceListService") + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + ;[priceLists, count] = await listAndCountPriceListPricingModule({ + filters: req.filterableFields, + listConfig: req.listConfig, + container: req.scope as MedusaContainer, + }) + } else { + const priceListService: PriceListService = + req.scope.resolve("priceListService") - const [price_lists, count] = await priceListService.listAndCount( - req.filterableFields, - req.listConfig - ) + ;[priceLists, count] = await priceListService.listAndCount( + req.filterableFields, + req.listConfig + ) + } res.json({ - price_lists, + price_lists: priceLists, count, offset: validated.offset, limit: validated.limit, diff --git a/packages/medusa/src/api/routes/admin/price-lists/modules-queries/get-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/get-price-list.ts new file mode 100644 index 0000000000000..3f13f6fb47f26 --- /dev/null +++ b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/get-price-list.ts @@ -0,0 +1,29 @@ +import { MedusaContainer } from "@medusajs/types" +import { PriceList } from "../../../../../models" +import { MedusaError } from "medusa-core-utils" +import { listAndCountPriceListPricingModule } from "./list-and-count-price-lists" + +export async function getPriceListPricingModule( + id: string, + { + container, + }: { + container: MedusaContainer + } +): Promise { + const [priceLists, count] = await listAndCountPriceListPricingModule({ + filters: { + id: [id], + }, + container, + }) + + if (count === 0) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `Price list with id: ${id} was not found` + ) + } + + return priceLists[0] +} diff --git a/packages/medusa/src/api/routes/admin/price-lists/modules-queries/index.ts b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/index.ts new file mode 100644 index 0000000000000..f97cec663cbee --- /dev/null +++ b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/index.ts @@ -0,0 +1,2 @@ +export * from "./get-price-list" +export * from "./list-and-count-price-lists" diff --git a/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts new file mode 100644 index 0000000000000..179d160445c40 --- /dev/null +++ b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts @@ -0,0 +1,104 @@ +import { FilterablePriceListProps, MedusaContainer } from "@medusajs/types" +import { FindConfig } from "../../../../../types/common" +import { CustomerGroup, MoneyAmount, PriceList } from "../../../../../models" +import { CustomerGroupService } from "../../../../../services" +import { defaultAdminPriceListRemoteQueryObject } from "../index" + +export async function listAndCountPriceListPricingModule({ + filters, + listConfig = { skip: 0 }, + container, +}: { + container: MedusaContainer + filters?: FilterablePriceListProps + listConfig?: FindConfig +}): Promise<[PriceList[], number]> { + const remoteQuery = container.resolve("remoteQuery") + const customerGroupService: CustomerGroupService = container.resolve( + "customerGroupService" + ) + + const query = { + price_list: { + __args: { filters, ...listConfig }, + ...defaultAdminPriceListRemoteQueryObject, + }, + } + + const { + rows: priceLists, + metadata: { count }, + } = await remoteQuery(query) + + if (!count) { + return [[], 0] + } + + const customerGroupIds: string[] = priceLists + .map((priceList) => + priceList.price_list_rules + .filter((rule) => rule.rule_type.rule_attribute === "customer_group_id") + .map((rule) => + rule.price_list_rule_values.map((rule_value) => rule_value.value) + ) + ) + .flat(2) + + const priceListCustomerGroups = await customerGroupService.list( + { id: customerGroupIds }, + {} + ) + + const customerGroupIdCustomerGroupMap = new Map( + priceListCustomerGroups.map((customerGroup) => [ + customerGroup.id, + customerGroup, + ]) + ) + + for (const priceList of priceLists) { + const priceSetMoneyAmounts = priceList.price_set_money_amounts || [] + const priceListRulesData = priceList.price_list_rules || [] + delete priceList.price_set_money_amounts + delete priceList.price_list_rules + + priceList.prices = priceSetMoneyAmounts.map((priceSetMoneyAmount) => { + const productVariant = priceSetMoneyAmount.price_set.variant_link.variant + + return { + ...(priceSetMoneyAmount.money_amount as MoneyAmount), + price_list_id: priceList.id, + variant_id: productVariant?.id ?? null, + variant: productVariant ?? null, + region_id: null, + } + }) + + priceList.name = priceList.title + delete priceList.title + + const customerGroupPriceListRule = priceListRulesData.find( + (plr) => plr.rule_type.rule_attribute === "customer_group_id" + ) + + if ( + customerGroupPriceListRule && + customerGroupPriceListRule?.price_list_rule_values + ) { + priceList.customer_groups = + customerGroupPriceListRule?.price_list_rule_values + .map((customerGroupRule) => + customerGroupIdCustomerGroupMap.get(customerGroupRule.value) + ) + .filter( + ( + customerGroup: CustomerGroup | undefined + ): customerGroup is CustomerGroup => !!customerGroup + ) + } else { + priceList.customer_groups = [] + } + } + + return [priceLists, count] +} diff --git a/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts index 9ba8c3a561d5f..b00b582659dd2 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts @@ -1,4 +1,5 @@ -import { PriceListStatus, PriceListType } from "@medusajs/utils" +import { MedusaContainer, PricingTypes, WorkflowTypes } from "@medusajs/types" +import { MedusaV2Flag, PriceListStatus, PriceListType } from "@medusajs/utils" import { IsArray, IsBoolean, @@ -8,15 +9,17 @@ import { ValidateNested, } from "class-validator" import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "." -import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list" +import { updatePriceLists } from "@medusajs/workflows" import { Type } from "class-transformer" import { EntityManager } from "typeorm" import { PriceList } from "../../../.." import TaxInclusivePricingFeatureFlag from "../../../../loaders/feature-flags/tax-inclusive-pricing" import PriceListService from "../../../../services/price-list" +import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list" import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators" import { validator } from "../../../../utils/validator" +import { getPriceListPricingModule } from "./modules-queries" /** * @oas [post] /admin/price-lists/{id} @@ -83,26 +86,59 @@ import { validator } from "../../../../utils/validator" */ export default async (req, res) => { const { id } = req.params + let priceList + const featureFlagRouter = req.scope.resolve("featureFlagRouter") + const manager: EntityManager = req.scope.resolve("manager") + const priceListService: PriceListService = + req.scope.resolve("priceListService") const validated = await validator( AdminPostPriceListsPriceListPriceListReq, req.body ) - const priceListService: PriceListService = - req.scope.resolve("priceListService") + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + const updateVariantsWorkflow = updatePriceLists(req.scope) + const rules: PricingTypes.CreatePriceListRules = {} + const customerGroups = validated.customer_groups || [] + delete validated.customer_groups - const manager: EntityManager = req.scope.resolve("manager") - await manager.transaction(async (transactionManager) => { - return await priceListService - .withTransaction(transactionManager) - .update(id, validated) - }) - - const priceList = await priceListService.retrieve(id, { - select: defaultAdminPriceListFields as (keyof PriceList)[], - relations: defaultAdminPriceListRelations, - }) + if (customerGroups.length) { + rules["customer_group_id"] = customerGroups.map((group) => group.id) + } + + const input = { + price_lists: [ + { + id, + ...validated, + rules, + }, + ], + } as WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowInputDTO + + await updateVariantsWorkflow.run({ + input, + context: { + manager, + }, + }) + + priceList = await getPriceListPricingModule(id, { + container: req.scope as MedusaContainer, + }) + } else { + await manager.transaction(async (transactionManager) => { + return await priceListService + .withTransaction(transactionManager) + .update(id, validated) + }) + + priceList = await priceListService.retrieve(id, { + select: defaultAdminPriceListFields as (keyof PriceList)[], + relations: defaultAdminPriceListRelations, + }) + } res.json({ price_list: priceList }) } diff --git a/packages/medusa/src/api/routes/admin/products/create-variant.ts b/packages/medusa/src/api/routes/admin/products/create-variant.ts index ffddb375fb306..f394c73db2fe7 100644 --- a/packages/medusa/src/api/routes/admin/products/create-variant.ts +++ b/packages/medusa/src/api/routes/admin/products/create-variant.ts @@ -1,7 +1,6 @@ -import { - CreateProductVariantInput, - ProductVariantPricesCreateReq, -} from "../../../../types/product-variant" +import { IInventoryService, WorkflowTypes } from "@medusajs/types" +import { FlagRouter, MedusaV2Flag } from "@medusajs/utils" +import { CreateProductVariants } from "@medusajs/workflows" import { IsArray, IsBoolean, @@ -11,19 +10,22 @@ import { IsString, ValidateNested, } from "class-validator" +import { defaultAdminProductFields, defaultAdminProductRelations } from "." import { PricingService, ProductService, ProductVariantInventoryService, ProductVariantService, } from "../../../../services" -import { defaultAdminProductFields, defaultAdminProductRelations } from "." - -import { EntityManager } from "typeorm" -import { IInventoryService } from "@medusajs/types" +import { + CreateProductVariantInput, + ProductVariantPricesCreateReq, +} from "../../../../types/product-variant" import { Type } from "class-transformer" -import { createVariantsTransaction } from "./transaction/create-product-variant" +import { EntityManager } from "typeorm" import { validator } from "../../../../utils/validator" +import { getProductWithIsolatedProductModule } from "./get-product" +import { createVariantsTransaction } from "./transaction/create-product-variant" /** * @oas [post] /admin/products/{id}/variants @@ -122,6 +124,8 @@ export default async (req, res) => { req.body ) + const manager: EntityManager = req.scope.resolve("manager") + const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter") const inventoryService: IInventoryService | undefined = req.scope.resolve("inventoryService") const productVariantInventoryService: ProductVariantInventoryService = @@ -129,29 +133,56 @@ export default async (req, res) => { const productVariantService: ProductVariantService = req.scope.resolve( "productVariantService" ) + const pricingService: PricingService = req.scope.resolve("pricingService") + let rawProduct - const manager: EntityManager = req.scope.resolve("manager") + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + const createVariantsWorkflow = CreateProductVariants.createProductVariants( + req.scope + ) - await manager.transaction(async (transactionManager) => { - await createVariantsTransaction( - { - manager: transactionManager, - inventoryService, - productVariantInventoryService, - productVariantService, + const input = { + productVariants: [ + { + product_id: id, + ...validated, + }, + ] as WorkflowTypes.ProductWorkflow.CreateProductVariantsInputDTO[], + } + + await createVariantsWorkflow.run({ + input, + context: { + manager, }, + }) + + rawProduct = await getProductWithIsolatedProductModule( + req, id, - [validated as CreateProductVariantInput] + req.retrieveConfig ) - }) - - const productService: ProductService = req.scope.resolve("productService") - const pricingService: PricingService = req.scope.resolve("pricingService") - - const rawProduct = await productService.retrieve(id, { - select: defaultAdminProductFields, - relations: defaultAdminProductRelations, - }) + } else { + await manager.transaction(async (transactionManager) => { + await createVariantsTransaction( + { + manager: transactionManager, + inventoryService, + productVariantInventoryService, + productVariantService, + }, + id, + [validated as CreateProductVariantInput] + ) + }) + + const productService: ProductService = req.scope.resolve("productService") + + rawProduct = await productService.retrieve(id, { + select: defaultAdminProductFields, + relations: defaultAdminProductRelations, + }) + } const [product] = await pricingService.setAdminProductPricing([rawProduct]) diff --git a/packages/medusa/src/api/routes/admin/products/get-product.ts b/packages/medusa/src/api/routes/admin/products/get-product.ts index 9028a0ab9b50d..b1a238a79e2df 100644 --- a/packages/medusa/src/api/routes/admin/products/get-product.ts +++ b/packages/medusa/src/api/routes/admin/products/get-product.ts @@ -118,7 +118,11 @@ export default async (req, res) => { res.json({ product }) } -async function getProductWithIsolatedProductModule(req, id, retrieveConfig) { +export async function getProductWithIsolatedProductModule( + req, + id, + retrieveConfig +) { // TODO: Add support for fields/expands const remoteQuery = req.scope.resolve("remoteQuery") diff --git a/packages/medusa/src/api/routes/admin/products/list-products.ts b/packages/medusa/src/api/routes/admin/products/list-products.ts index d63809b4231ce..549b2603981b0 100644 --- a/packages/medusa/src/api/routes/admin/products/list-products.ts +++ b/packages/medusa/src/api/routes/admin/products/list-products.ts @@ -7,7 +7,11 @@ import { SalesChannelService, } from "../../../../services" -import { IInventoryService } from "@medusajs/types" +import { + IInventoryService, + IPricingModuleService, + IProductModuleService, +} from "@medusajs/types" import { MedusaV2Flag, promiseAll } from "@medusajs/utils" import { Type } from "class-transformer" import { Product } from "../../../../models" @@ -301,7 +305,53 @@ export default async (req, res) => { }) } -async function listAndCountProductWithIsolatedProductModule( +async function getVariantsFromPriceList(req, priceListId) { + const remoteQuery = req.scope.resolve("remoteQuery") + const pricingModuleService: IPricingModuleService = req.scope.resolve( + "pricingModuleService" + ) + const productModuleService: IProductModuleService = req.scope.resolve( + "productModuleService" + ) + + const [priceList] = await pricingModuleService.listPriceLists( + { id: [priceListId] }, + { + relations: [ + "price_set_money_amounts", + "price_set_money_amounts.price_set", + ], + select: ["price_set_money_amounts.price_set.id"], + } + ) + + const priceSetIds = priceList.price_set_money_amounts?.map( + (psma) => psma.price_set?.id + ) + + const query = { + product_variant_price_set: { + __args: { + price_set_id: priceSetIds, + }, + fields: ["variant_id", "price_set_id"], + }, + } + + const variantPriceSets = await remoteQuery(query) + const variantIds = variantPriceSets.map((vps) => vps.variant_id) + + return await productModuleService.listVariants( + { + id: variantIds, + }, + { + select: ["product_id"], + } + ) +} + +export async function listAndCountProductWithIsolatedProductModule( req, filterableFields, listConfig @@ -309,6 +359,7 @@ async function listAndCountProductWithIsolatedProductModule( // TODO: Add support for fields/expands const remoteQuery = req.scope.resolve("remoteQuery") + const featureFlagRouter = req.scope.resolve("featureFlagRouter") const productIdsFilter: Set = new Set() const variantIdsFilter: Set = new Set() @@ -352,22 +403,28 @@ async function listAndCountProductWithIsolatedProductModule( delete filterableFields.price_list_id if (priceListId) { - // TODO: it is working but validate the behaviour. - // e.g pricing context properly set. - // At the moment filtering by price list but not having any customer id or - // include discount forces the query to filter with price list id is null - const priceListService = req.scope.resolve( - "priceListService" - ) as PriceListService - promises.push( - priceListService - .listPriceListsVariantIdsMap(priceListId) - .then((priceListVariantIdsMap) => { - priceListVariantIdsMap[priceListId].map((variantId) => - variantIdsFilter.add(variantId) - ) - }) - ) + if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { + const variants = await getVariantsFromPriceList(req, priceListId) + + variants.forEach((pv) => variantIdsFilter.add(pv.id)) + } else { + // TODO: it is working but validate the behaviour. + // e.g pricing context properly set. + // At the moment filtering by price list but not having any customer id or + // include discount forces the query to filter with price list id is null + const priceListService = req.scope.resolve( + "priceListService" + ) as PriceListService + promises.push( + priceListService + .listPriceListsVariantIdsMap(priceListId) + .then((priceListVariantIdsMap) => { + priceListVariantIdsMap[priceListId].map((variantId) => + variantIdsFilter.add(variantId) + ) + }) + ) + } } const discountConditionId = filterableFields.discount_condition_id diff --git a/packages/medusa/src/commands/migrate.js b/packages/medusa/src/commands/migrate.js index 981808b5a473a..f335104a193cf 100644 --- a/packages/medusa/src/commands/migrate.js +++ b/packages/medusa/src/commands/migrate.js @@ -5,7 +5,7 @@ import getMigrations, { runIsolatedModulesMigration, } from "./utils/get-migrations" -import { MedusaV2Flag, createMedusaContainer } from "@medusajs/utils" +import { createMedusaContainer } from "@medusajs/utils" import configModuleLoader from "../loaders/config" import databaseLoader from "../loaders/database" import featureFlagLoader from "../loaders/feature-flags" @@ -38,6 +38,11 @@ const getDataSource = async (directory) => { const runLinkMigrations = async (directory) => { const configModule = configModuleLoader(directory) const container = createMedusaContainer() + const featureFlagRouter = featureFlagLoader(configModule) + + container.register({ + featureFlagRouter: asValue(featureFlagRouter), + }) await pgConnectionLoader({ configModule, container }) @@ -63,16 +68,13 @@ const main = async function ({ directory }) { const configModule = configModuleLoader(directory) const dataSource = await getDataSource(directory) - const featureFlagRouter = featureFlagLoader(configModule) if (args[0] === "run") { await dataSource.runMigrations() await dataSource.destroy() await runIsolatedModulesMigration(configModule) - if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { - await runLinkMigrations(directory) - } + await runLinkMigrations(directory) process.exit() Logger.info("Migrations completed.") diff --git a/packages/medusa/src/loaders/plugins.ts b/packages/medusa/src/loaders/plugins.ts index 356c5d3f5ce3c..a5db6bc287931 100644 --- a/packages/medusa/src/loaders/plugins.ts +++ b/packages/medusa/src/loaders/plugins.ts @@ -96,6 +96,7 @@ export default async ({ ) registerCoreRouters(pluginDetails, container) await registerSubscribers(pluginDetails, container, activityId) + await registerWorkflows(pluginDetails) }) ) @@ -634,6 +635,15 @@ function registerRepositories( }) } +/** + * import files from the workflows directory to run the registration of the wofklows + * @param pluginDetails + */ +async function registerWorkflows(pluginDetails: PluginDetails): Promise { + const files = glob.sync(`${pluginDetails.resolve}/workflows/*.js`, {}) + await Promise.all(files.map(async (file) => import(file))) +} + /** * Registers a plugin's models at the right location in our container. Models * must inherit from BaseModel. Models are registered directly in the container. diff --git a/packages/medusa/src/migrations/1699371074198-drop-non-null-constraint-price-list.ts b/packages/medusa/src/migrations/1699371074198-drop-non-null-constraint-price-list.ts new file mode 100644 index 0000000000000..be2a73a515c8b --- /dev/null +++ b/packages/medusa/src/migrations/1699371074198-drop-non-null-constraint-price-list.ts @@ -0,0 +1,20 @@ +import { MedusaV2Flag } from "@medusajs/utils" +import { MigrationInterface, QueryRunner } from "typeorm" + +export const featureFlag = MedusaV2Flag.key + +export class DropNonNullConstraintPriceList1699371074198 + implements MigrationInterface +{ + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE IF EXISTS price_list ALTER COLUMN name DROP NOT NULL; + `) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE IF EXISTS price_list ALTER COLUMN name SET NOT NULL; + `) + } +} diff --git a/packages/medusa/src/models/money-amount.ts b/packages/medusa/src/models/money-amount.ts index db172c17d9707..0ecece7eb8c56 100644 --- a/packages/medusa/src/models/money-amount.ts +++ b/packages/medusa/src/models/money-amount.ts @@ -69,7 +69,7 @@ export class MoneyAmount extends SoftDeletableEntity { @Index("idx_money_amount_region_id") @Column({ nullable: true }) - region_id: string + region_id: string | null @ManyToOne(() => Region) @JoinColumn({ name: "region_id" }) diff --git a/packages/medusa/src/scripts/create-default-rule-types.ts b/packages/medusa/src/scripts/create-default-rule-types.ts index 66e26996b6978..b5d2612c36cea 100644 --- a/packages/medusa/src/scripts/create-default-rule-types.ts +++ b/packages/medusa/src/scripts/create-default-rule-types.ts @@ -1,29 +1,10 @@ -import { AwilixContainer } from "awilix" -import { IPricingModuleService } from "@medusajs/types" +import { createDefaultRuleTypes } from "./utils/create-default-rule-types" import dotenv from "dotenv" import express from "express" import loaders from "../loaders" dotenv.config() -export const createDefaultRuleTypes = async (container: AwilixContainer) => { - const pricingModuleService: IPricingModuleService = container.resolve( - "pricingModuleService" - ) - const existing = await pricingModuleService.listRuleTypes( - { rule_attribute: ["region_id"] }, - { take: 1 } - ) - - if (existing.length) { - return - } - - await pricingModuleService.createRuleTypes([ - { name: "region_id", rule_attribute: "region_id" }, - ]) -} - const migrate = async function ({ directory }) { const app = express() const { container } = await loaders({ @@ -38,7 +19,9 @@ const migrate = async function ({ directory }) { migrate({ directory: process.cwd() }) .then(() => { console.log("Created default rule types") + process.exit() }) .catch(() => { console.log("Failed to create rule types") + process.exit(1) }) diff --git a/packages/medusa/src/scripts/migrate-to-pricing-module.ts b/packages/medusa/src/scripts/migrate-to-pricing-module.ts new file mode 100644 index 0000000000000..46e503b2b3503 --- /dev/null +++ b/packages/medusa/src/scripts/migrate-to-pricing-module.ts @@ -0,0 +1,250 @@ +import { IPricingModuleService, PricingTypes } from "@medusajs/types" +import { promiseAll } from "@medusajs/utils" +import { AwilixContainer } from "awilix" +import dotenv from "dotenv" +import express from "express" +import loaders from "../loaders" +import Logger from "../loaders/logger" +import { PriceList } from "../models" +import { CurrencyService, PriceListService } from "../services" +import { createDefaultRuleTypes } from "./utils/create-default-rule-types" +import { migrateProductVariantPricing } from "./utils/migrate-money-amounts-to-pricing-module" + +dotenv.config() + +const BATCH_SIZE = 1000 + +const migratePriceLists = async (container: AwilixContainer) => { + const pricingModuleService: IPricingModuleService = container.resolve( + "pricingModuleService" + ) + let offset = 0 + + const priceListCoreService: PriceListService = + container.resolve("priceListService") + + const remoteQuery = container.resolve("remoteQuery") + + const [_, totalCount] = await priceListCoreService.listAndCount( + {}, + { select: ["id"] } + ) + + while (offset < totalCount) { + const corePriceLists = await priceListCoreService.list( + {}, + { + take: BATCH_SIZE, + skip: offset, + relations: ["customer_groups", "prices", "prices.variants"], + } + ) + + const pricingModulePriceLists = await pricingModuleService.listPriceLists( + { id: corePriceLists.map(({ id }) => id) }, + { + take: BATCH_SIZE, + skip: offset, + select: ["id"], + } + ) + + const priceListIdsToUpdateSet = new Set( + pricingModulePriceLists.map(({ id }) => id) + ) + + const priceListsToCreate: PriceList[] = [] + const priceListsToUpdate: PriceList[] = [] + const variantIds: string[] = [] + + for (const corePriceList of corePriceLists) { + if (priceListIdsToUpdateSet.has(corePriceList.id)) { + priceListsToCreate.push(corePriceList) + } else { + priceListsToUpdate.push(corePriceList) + } + + const corePrices = corePriceList.prices || [] + + variantIds.push( + ...corePrices.map((corePrice) => corePrice.variants?.[0]?.id) + ) + } + + const query = { + product_variant_price_set: { + __args: { + variant_id: variantIds, + }, + fields: ["variant_id", "price_set_id"], + }, + } + + const variantPriceSets = await remoteQuery(query) + + const variantIdPriceSetIdMap = new Map( + variantPriceSets.map((vps) => [vps.variant_id, vps.price_set_id]) + ) + + const promises: Promise[] = [] + + if (priceListsToUpdate.length) { + await pricingModuleService.updatePriceLists( + priceListsToUpdate.map((priceList) => { + const updateData: PricingTypes.UpdatePriceListDTO = { + id: priceList.id, + title: priceList.name, + } + + if (priceList?.customer_groups?.length) { + updateData.rules = { + customer_group_id: priceList.customer_groups.map(({ id }) => id), + } + } + + return updateData + }) + ) + + promises.push( + pricingModuleService.addPriceListPrices( + priceListsToUpdate.map((priceList) => { + return { + priceListId: priceList.id, + prices: priceList.prices + .filter((price) => + variantIdPriceSetIdMap.has(price.variants?.[0]?.id) + ) + .map((price) => { + return { + price_set_id: variantIdPriceSetIdMap.get( + price.variants?.[0]?.id + )!, + currency_code: price.currency_code, + amount: price.amount, + min_quantity: price.min_quantity, + max_quantity: price.max_quantity, + } + }), + } + }) + ) + ) + } + + if (priceListsToCreate.length) { + promises.push( + pricingModuleService.createPriceLists( + priceListsToCreate.map( + ({ name: title, prices, customer_groups, ...priceList }) => { + const createData: PricingTypes.CreatePriceListDTO = { + ...priceList, + starts_at: priceList.starts_at?.toISOString(), + ends_at: priceList.ends_at?.toISOString(), + title, + } + + if (customer_groups?.length) { + createData.rules = { + customer_group_id: customer_groups.map(({ id }) => id), + } + } + + if (prices?.length) { + createData.prices = prices.map((price) => { + return { + price_set_id: variantIdPriceSetIdMap.get( + price.variants?.[0]?.id + )!, + currency_code: price.currency_code, + amount: price.amount, + min_quantity: price.min_quantity, + max_quantity: price.max_quantity, + } + }) + } + + return createData + } + ) + ) + ) + } + + await promiseAll(promises) + + offset += corePriceLists.length + + Logger.info(`Processed ${offset} of ${totalCount}`) + } +} + +const ensureCurrencies = async (container: AwilixContainer) => { + const currenciesService: CurrencyService = + container.resolve("currencyService") + + const pricingModuleService: IPricingModuleService = container.resolve( + "pricingModuleService" + ) + + const [coreCurrencies, totalCurrencies] = + await currenciesService.listAndCount({}, {}) + + const moduleCurrencies = await pricingModuleService.listCurrencies( + {}, + { take: 100000 } + ) + + const moduleCurrenciesSet = new Set(moduleCurrencies.map(({ code }) => code)) + + const currenciesToCreate = coreCurrencies + .filter(({ code }) => { + return !moduleCurrenciesSet.has(code) + }) + .map(({ includes_tax, ...currency }) => currency) + + await pricingModuleService.createCurrencies(currenciesToCreate) +} + +const migrate = async function ({ directory }) { + const app = express() + + const { container } = await loaders({ + directory, + expressApp: app, + isTest: false, + }) + + Logger.info("-----------------------------------------------") + Logger.info("------------- Creating currencies -------------") + Logger.info("-----------------------------------------------") + await ensureCurrencies(container) + + Logger.info("-----------------------------------------------") + Logger.info("--------- Creating default rule types ---------") + Logger.info("-----------------------------------------------") + await createDefaultRuleTypes(container) + + Logger.info("-----------------------------------------------") + Logger.info("---------- Migrating Variant Prices -----------") + Logger.info("-----------------------------------------------") + + await migrateProductVariantPricing(container) + + Logger.info("-----------------------------------------------") + Logger.info("----------- Migrating Price Lists -------------") + Logger.info("-----------------------------------------------") + + return await migratePriceLists(container) +} + +migrate({ directory: process.cwd() }) + .then(() => { + Logger.info("Migrated price lists") + process.exit(0) + }) + .catch((error) => { + console.warn(error) + Logger.info("Failed to migrate price lists") + process.exit(1) + }) diff --git a/packages/medusa/src/scripts/money-amount-pricing-module-migration.ts b/packages/medusa/src/scripts/money-amount-pricing-module-migration.ts deleted file mode 100644 index 3ff98ac98b0dd..0000000000000 --- a/packages/medusa/src/scripts/money-amount-pricing-module-migration.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { IPricingModuleService, MedusaContainer } from "@medusajs/types" -import { - FlagRouter, - MedusaError, - MedusaV2Flag, - promiseAll, -} from "@medusajs/utils" -import dotenv from "dotenv" -import express from "express" -import { EntityManager } from "typeorm" -import loaders from "../loaders" -import loadMedusaApp from "../loaders/medusa-app" -import { ProductVariant } from "../models" -import { ProductVariantService } from "../services" -import { createDefaultRuleTypes } from "./create-default-rule-types" - -dotenv.config() - -const BATCH_SIZE = 100 - -const migrateProductVariant = async ( - variant: ProductVariant, - { - container, - }: { container: MedusaContainer; transactionManager: EntityManager } -) => { - const pricingService: IPricingModuleService = container.resolve( - "pricingModuleService" - ) - - const configModule = await container.resolve("configModule") - const { link } = await loadMedusaApp( - { configModule, container }, - { registerInContainer: false } - ) - - if (!link) { - throw new MedusaError( - MedusaError.Types.NOT_ALLOWED, - "Can't migrate money_amounts: Pricing module is not configured correctly" - ) - } - - const priceSet = await pricingService.create({ - rules: [{ rule_attribute: "region_id" }], - prices: variant.prices.map((price) => ({ - rules: { - region_id: price.region_id, - }, - currency_code: price.currency_code, - min_quantity: price.min_quantity, - max_quantity: price.max_quantity, - amount: price.amount, - })), - }) - - await link.create({ - productService: { - variant_id: variant.id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }) -} - -const processBatch = async ( - variants: ProductVariant[], - container: MedusaContainer -) => { - const manager = container.resolve("manager") - return await manager.transaction(async (transactionManager) => { - await promiseAll( - variants.map(async (variant) => { - await migrateProductVariant(variant, { - container, - transactionManager, - }) - }) - ) - }) -} - -const migrate = async function ({ directory }) { - const app = express() - const { container } = await loaders({ - directory, - expressApp: app, - isTest: false, - }) - - const variantService: ProductVariantService = await container.resolve( - "productVariantService" - ) - const featureFlagRouter: FlagRouter = await container.resolve( - "featureFlagRouter" - ) - - if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { - throw new MedusaError( - MedusaError.Types.NOT_ALLOWED, - "Pricing module not enabled" - ) - } - - await createDefaultRuleTypes(container) - - const [variants, totalCount] = await variantService.listAndCount( - {}, - { take: BATCH_SIZE, order: { id: "ASC" }, relations: ["prices"] } - ) - - await processBatch(variants, container) - - let processedCount = variants.length - - console.log(`Processed ${processedCount} of ${totalCount}`) - - while (processedCount < totalCount) { - const nextBatch = await variantService.list( - {}, - { - skip: processedCount, - take: BATCH_SIZE, - order: { id: "ASC" }, - relations: ["prices"], - } - ) - - await processBatch(nextBatch, container) - - processedCount += nextBatch.length - console.log(`Processed ${processedCount} of ${totalCount}`) - } - - console.log("Done") - process.exit(0) -} - -migrate({ directory: process.cwd() }) diff --git a/packages/medusa/src/scripts/utils/create-default-rule-types.ts b/packages/medusa/src/scripts/utils/create-default-rule-types.ts new file mode 100644 index 0000000000000..6403b98d03e52 --- /dev/null +++ b/packages/medusa/src/scripts/utils/create-default-rule-types.ts @@ -0,0 +1,31 @@ +import { AwilixContainer } from "awilix" +import { IPricingModuleService } from "@medusajs/types" + +export const createDefaultRuleTypes = async (container: AwilixContainer) => { + const pricingModuleService: IPricingModuleService = container.resolve( + "pricingModuleService" + ) + const existing = await pricingModuleService.listRuleTypes( + { rule_attribute: ["region_id", "customer_group_id"] }, + { take: 2 } + ) + + if (existing.length === 2) { + return + } + + if (existing.length === 0) { + await pricingModuleService.createRuleTypes([ + { name: "region_id", rule_attribute: "region_id" }, + { name: "customer_group_id", rule_attribute: "customer_group_id" }, + ]) + } else if (existing[0].rule_attribute === "region_id") { + await pricingModuleService.createRuleTypes([ + { name: "customer_group_id", rule_attribute: "customer_group_id" }, + ]) + } else { + await pricingModuleService.createRuleTypes([ + { name: "region_id", rule_attribute: "region_id" }, + ]) + } +} diff --git a/packages/medusa/src/scripts/utils/migrate-money-amounts-to-pricing-module.ts b/packages/medusa/src/scripts/utils/migrate-money-amounts-to-pricing-module.ts new file mode 100644 index 0000000000000..4a1e26076acc0 --- /dev/null +++ b/packages/medusa/src/scripts/utils/migrate-money-amounts-to-pricing-module.ts @@ -0,0 +1,83 @@ +import { IPricingModuleService, MedusaContainer } from "@medusajs/types" +import { MedusaError, promiseAll } from "@medusajs/utils" + +import { ProductVariantService } from "../../services" +import dotenv from "dotenv" + +dotenv.config() + +const BATCH_SIZE = 100 + +export const migrateProductVariantPricing = async function ( + container: MedusaContainer +) { + const variantService: ProductVariantService = await container.resolve( + "productVariantService" + ) + + const pricingService: IPricingModuleService = container.resolve( + "pricingModuleService" + ) + + const link = await container.resolve("remoteLink") + + if (!link) { + throw new MedusaError( + MedusaError.Types.NOT_ALLOWED, + "Can't migrate money_amounts: Pricing module is not configured correctly" + ) + } + + const [_, totalCount] = await variantService.listAndCount( + {}, + { take: BATCH_SIZE, order: { id: "ASC" }, relations: ["prices"] } + ) + + let processedCount = 0 + while (processedCount < totalCount) { + const [variants] = await variantService.listAndCount( + {}, + { + skip: processedCount, + take: BATCH_SIZE, + order: { id: "ASC" }, + relations: ["prices"], + } + ) + + const links: any[] = [] + + await promiseAll( + variants.map(async (variant) => { + const priceSet = await pricingService.create({ + rules: [{ rule_attribute: "region_id" }], + prices: + variant?.prices + ?.filter(({ price_list_id }) => !price_list_id) + .map((price) => ({ + rules: { + ...(price.region_id ? { region_id: price.region_id } : {}), + }, + currency_code: price.currency_code, + min_quantity: price.min_quantity, + max_quantity: price.max_quantity, + amount: price.amount, + })) ?? [], + }) + + links.push({ + productService: { + variant_id: variant.id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }) + }) + ) + await link.create(links) + + processedCount += variants.length + console.log(`Processed ${processedCount} of ${totalCount}`) + } +} diff --git a/packages/medusa/src/services/pricing.ts b/packages/medusa/src/services/pricing.ts index de1265db5f0dc..79c0752fc78b2 100644 --- a/packages/medusa/src/services/pricing.ts +++ b/packages/medusa/src/services/pricing.ts @@ -4,15 +4,18 @@ import { PriceSetMoneyAmountDTO, RemoteQueryFunction, } from "@medusajs/types" - +import { + CustomerService, + ProductVariantService, + RegionService, + TaxProviderService, +} from "." import { FlagRouter, MedusaV2Flag, promiseAll, removeNullish, } from "@medusajs/utils" -import { ProductVariantService, RegionService, TaxProviderService } from "." - import { IPriceSelectionStrategy, PriceSelectionContext, @@ -33,11 +36,11 @@ import { TaxedPricing, } from "../types/pricing" -import { MedusaError } from "medusa-core-utils" import { EntityManager } from "typeorm" -import { TransactionBaseService } from "../interfaces" +import { MedusaError } from "medusa-core-utils" import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing" import { TaxServiceRate } from "../types/tax-service" +import { TransactionBaseService } from "../interfaces" import { calculatePriceTaxAmount } from "../utils" type InjectedDependencies = { @@ -45,6 +48,7 @@ type InjectedDependencies = { productVariantService: ProductVariantService taxProviderService: TaxProviderService regionService: RegionService + customerService: CustomerService priceSelectionStrategy: IPriceSelectionStrategy featureFlagRouter: FlagRouter remoteQuery: RemoteQueryFunction @@ -57,6 +61,7 @@ type InjectedDependencies = { class PricingService extends TransactionBaseService { protected readonly regionService: RegionService protected readonly taxProviderService: TaxProviderService + protected readonly customerService_: CustomerService protected readonly priceSelectionStrategy: IPriceSelectionStrategy protected readonly productVariantService: ProductVariantService protected readonly featureFlagRouter: FlagRouter @@ -64,6 +69,7 @@ class PricingService extends TransactionBaseService { protected get pricingModuleService(): IPricingModuleService { return this.__container__.pricingModuleService } + protected get remoteQuery(): RemoteQueryFunction { return this.__container__.remoteQuery } @@ -74,6 +80,7 @@ class PricingService extends TransactionBaseService { regionService, priceSelectionStrategy, featureFlagRouter, + customerService, }: InjectedDependencies) { // eslint-disable-next-line prefer-rest-params super(arguments[0]) @@ -82,6 +89,7 @@ class PricingService extends TransactionBaseService { this.taxProviderService = taxProviderService this.priceSelectionStrategy = priceSelectionStrategy this.productVariantService = productVariantService + this.customerService_ = customerService this.featureFlagRouter = featureFlagRouter } @@ -220,9 +228,20 @@ class PricingService extends TransactionBaseService { (variantPriceSet) => variantPriceSet.price_set_id ) - const queryContext: PriceSelectionContext = removeNullish( - context.price_selection - ) + const queryContext: PriceSelectionContext & { + customer_group_id?: string[] + } = removeNullish(context.price_selection) + + if (queryContext.customer_id) { + const { groups } = await this.customerService_.retrieve( + queryContext.customer_id, + { relations: ["groups"] } + ) + + if (groups?.length) { + queryContext.customer_group_id = groups.map((group) => group.id) + } + } let calculatedPrices: CalculatedPriceSet[] = [] @@ -259,25 +278,37 @@ class PricingService extends TransactionBaseService { } if (priceSetId) { - const calculatedPrice: CalculatedPriceSet | undefined = + const calculatedPrices: CalculatedPriceSet | undefined = calculatedPriceMap.get(priceSetId) - if (calculatedPrice) { - pricingResult.prices = [ - { - id: calculatedPrice.calculated_price?.money_amount_id, - currency_code: calculatedPrice.currency_code, - amount: calculatedPrice.calculated_amount, - min_quantity: calculatedPrice.calculated_price?.min_quantity, - max_quantity: calculatedPrice.calculated_price?.max_quantity, - price_list_id: calculatedPrice.calculated_price?.price_list_id, - }, - ] as MoneyAmount[] - - pricingResult.original_price = calculatedPrice?.original_amount - pricingResult.calculated_price = calculatedPrice?.calculated_amount + if (calculatedPrices) { + pricingResult.prices.push({ + id: calculatedPrices?.original_price?.money_amount_id, + currency_code: calculatedPrices.currency_code, + amount: calculatedPrices.original_amount, + min_quantity: calculatedPrices.original_price?.min_quantity, + max_quantity: calculatedPrices.original_price?.max_quantity, + price_list_id: calculatedPrices.original_price?.price_list_id, + } as MoneyAmount) + + if ( + calculatedPrices.calculated_price?.money_amount_id !== + calculatedPrices.original_price?.money_amount_id + ) { + pricingResult.prices.push({ + id: calculatedPrices.calculated_price?.money_amount_id, + currency_code: calculatedPrices.currency_code, + amount: calculatedPrices.calculated_amount, + min_quantity: calculatedPrices.calculated_price?.min_quantity, + max_quantity: calculatedPrices.calculated_price?.max_quantity, + price_list_id: calculatedPrices.calculated_price?.price_list_id, + } as MoneyAmount) + } + + pricingResult.original_price = calculatedPrices?.original_amount + pricingResult.calculated_price = calculatedPrices?.calculated_amount pricingResult.calculated_price_type = - calculatedPrice?.calculated_price?.price_list_type + calculatedPrices?.calculated_price?.price_list_type } } diff --git a/packages/medusa/src/types/price-list.ts b/packages/medusa/src/types/price-list.ts index 24ea5e1225790..208001af42ea3 100644 --- a/packages/medusa/src/types/price-list.ts +++ b/packages/medusa/src/types/price-list.ts @@ -9,7 +9,7 @@ import { ValidateNested, } from "class-validator" import { PriceList } from "../models/price-list" -import { DateComparisonOperator, FindConfig } from "./common" +import { DateComparisonOperator } from "./common" import { XorConstraint } from "./validators/xor" /** diff --git a/packages/orchestration/src/workflow/workflow-manager.ts b/packages/orchestration/src/workflow/workflow-manager.ts index e46f300f5bf5f..634c63b0fe138 100644 --- a/packages/orchestration/src/workflow/workflow-manager.ts +++ b/packages/orchestration/src/workflow/workflow-manager.ts @@ -70,7 +70,7 @@ export class WorkflowManager { static register( workflowId: string, - flow: TransactionStepsDefinition | OrchestratorBuilder, + flow: TransactionStepsDefinition | OrchestratorBuilder | undefined, handlers: WorkflowHandler, requiredModules?: Set, optionalModules?: Set @@ -78,19 +78,22 @@ export class WorkflowManager { const finalFlow = flow instanceof OrchestratorBuilder ? flow.build() : flow if (WorkflowManager.workflows.has(workflowId)) { - const areStepsEqual = - JSON.stringify(finalFlow) === - JSON.stringify(WorkflowManager.workflows.get(workflowId)!.flow_) + const areStepsEqual = finalFlow + ? JSON.stringify(finalFlow) === + JSON.stringify(WorkflowManager.workflows.get(workflowId)!.flow_) + : true if (!areStepsEqual) { - throw new Error(`Workflow with id "${workflowId}" and step definition already exists.`) + throw new Error( + `Workflow with id "${workflowId}" and step definition already exists.` + ) } } WorkflowManager.workflows.set(workflowId, { id: workflowId, - flow_: finalFlow, - orchestrator: new TransactionOrchestrator(workflowId, finalFlow), + flow_: finalFlow!, + orchestrator: new TransactionOrchestrator(workflowId, finalFlow ?? {}), handler: WorkflowManager.buildHandlers(handlers), handlers_: handlers, requiredModules, diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts index 659ac3e350360..734c96da15a24 100644 --- a/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts @@ -1185,6 +1185,77 @@ describe("PricingModule Service - Calculate Price", () => { ]) }) + it("should return best price list price first when price list conditions match", async () => { + await createPriceLists(service) + await createPriceLists( + service, + {}, + {}, + defaultPriceListPrices.map((price) => { + return { ...price, amount: price.amount / 2 } + }) + ) + + const priceSetsResult = await service.calculatePrices( + { id: ["price-set-EUR", "price-set-PLN"] }, + { + context: { + currency_code: "PLN", + region_id: "DE", + customer_group_id: "vip-customer-group-id", + company_id: "medusa-company-id", + }, + } + ) + + expect(priceSetsResult).toEqual([ + { + id: "price-set-EUR", + is_calculated_price_price_list: false, + calculated_amount: null, + is_original_price_price_list: false, + original_amount: null, + currency_code: null, + calculated_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + }, + { + id: "price-set-PLN", + is_calculated_price_price_list: true, + calculated_amount: 116, + is_original_price_price_list: false, + original_amount: 400, + currency_code: "PLN", + calculated_price: { + money_amount_id: expect.any(String), + price_list_id: expect.any(String), + price_list_type: "sale", + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: expect.any(String), + price_list_id: null, + price_list_type: null, + min_quantity: 1, + max_quantity: 5, + }, + }, + ]) + }) + it("should return price list prices when price list dont have rules, but context is loaded", async () => { await createPriceLists(service, {}, {}) diff --git a/packages/pricing/src/joiner-config.ts b/packages/pricing/src/joiner-config.ts index ee9c415f72904..7be13f7c8b88a 100644 --- a/packages/pricing/src/joiner-config.ts +++ b/packages/pricing/src/joiner-config.ts @@ -1,12 +1,20 @@ import { Modules } from "@medusajs/modules-sdk" import { ModuleJoinerConfig } from "@medusajs/types" import { MapToConfig } from "@medusajs/utils" -import { Currency, MoneyAmount, PriceSet } from "@models" +import { + Currency, + MoneyAmount, + PriceList, + PriceSet, + PriceSetMoneyAmount, +} from "@models" export const LinkableKeys = { money_amount_id: MoneyAmount.name, currency_code: Currency.name, price_set_id: PriceSet.name, + price_list_id: PriceList.name, + price_set_money_amount_id: PriceSetMoneyAmount.name, } const entityLinkableKeysMap: MapToConfig = {} Object.entries(LinkableKeys).forEach(([key, value]) => { @@ -16,11 +24,12 @@ Object.entries(LinkableKeys).forEach(([key, value]) => { valueFrom: key.split("_").pop()!, }) }) + export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap export const joinerConfig: ModuleJoinerConfig = { serviceName: Modules.PRICING, - primaryKeys: ["id", "currency_code"], + primaryKeys: ["id"], linkableKeys: LinkableKeys, alias: [ { @@ -53,5 +62,17 @@ export const joinerConfig: ModuleJoinerConfig = { methodSuffix: "Currencies", }, }, + { + name: "price_list", + args: { + methodSuffix: "PriceLists", + }, + }, + { + name: "price_lists", + args: { + methodSuffix: "PriceLists", + }, + }, ], } diff --git a/packages/pricing/src/migrations/Migration20231101232834.ts b/packages/pricing/src/migrations/Migration20231101232834.ts index 8056911665cea..a50aad2cd9987 100644 --- a/packages/pricing/src/migrations/Migration20231101232834.ts +++ b/packages/pricing/src/migrations/Migration20231101232834.ts @@ -14,13 +14,10 @@ export class Migration20231101232834 extends Migration { ) this.addSql( - `ALTER TABLE price_list ADD COLUMN IF NOT EXISTS number_rules integer not null default 0` + `ALTER TABLE price_list + ADD COLUMN IF NOT EXISTS number_rules integer not null default 0` ) - - this.addSql( - 'alter table "price_list" add column if not exists "title" text not null, add column if not exists "description" text not null, add column if not exists "type" text check ("type" in (\'sale\', \'override\')) not null default \'sale\';' - ) - + this.addSql( 'alter table "price_set_money_amount" drop constraint "price_set_money_amount_price_list_id_foreign";' ) @@ -30,9 +27,19 @@ export class Migration20231101232834 extends Migration { ) this.addSql( - 'alter table "price_list" add column if not exists "title" text not null, add column if not exists "description" text not null, add column if not exists "type" text check ("type" in (\'sale\', \'override\')) not null default \'sale\', add column if not exists "created_at" timestamptz not null default now(), add column if not exists "updated_at" timestamptz not null default now(), add column if not exists "deleted_at" timestamptz null;' + 'alter table "price_list" add column if not exists "title" text, add column if not exists "name" text, add column if not exists "description" text not null, add column if not exists "type" text check ("type" in (\'sale\', \'override\')) not null default \'sale\', add column if not exists "created_at" timestamptz not null default now(), add column if not exists "updated_at" timestamptz not null default now(), add column if not exists "deleted_at" timestamptz null;' ) + this.addSql(` + UPDATE "price_list" + SET title = name + `) + + this.addSql(`alter table "price_list" + alter column "title" set not null `) + + this.addSql('alter table "price_list" drop column if exists "name";') + this.addSql( 'create index if not exists "IDX_price_list_deleted_at" on "price_list" ("deleted_at");' ) diff --git a/packages/pricing/src/models/price-rule.ts b/packages/pricing/src/models/price-rule.ts index aab8908a656fe..a1d786759bda1 100644 --- a/packages/pricing/src/models/price-rule.ts +++ b/packages/pricing/src/models/price-rule.ts @@ -39,9 +39,6 @@ export default class PriceRule { }) rule_type: RuleType - @Property({ columnType: "boolean", default: false }) - is_dynamic: boolean - @Property({ columnType: "text" }) value: string diff --git a/packages/pricing/src/repositories/pricing.ts b/packages/pricing/src/repositories/pricing.ts index 6aadce388621b..9e12f4a491b50 100644 --- a/packages/pricing/src/repositories/pricing.ts +++ b/packages/pricing/src/repositories/pricing.ts @@ -71,6 +71,9 @@ export class PricingRepository price_list_id: "psma1.price_list_id", pl_number_rules: "pl.number_rules", pl_type: "pl.type", + has_price_list: knex.raw( + "case when psma1.price_list_id IS NULL then False else True end" + ), }) .leftJoin("price_set_money_amount as psma1", "psma1.id", "psma1.id") .leftJoin("price_rule as pr", "pr.price_set_money_amount_id", "psma1.id") @@ -154,15 +157,23 @@ export class PricingRepository .leftJoin("rule_type as rt", "rt.id", "pr.rule_type_id") .whereIn("ps.id", pricingFilters.id) .andWhere("ma.currency_code", "=", currencyCode) + .orderBy([ - { column: "price_list_id", order: "asc" }, + { column: "psma.has_price_list", order: "asc" }, { column: "number_rules", order: "desc" }, { column: "default_priority", order: "desc" }, + { column: "amount", order: "asc" }, ]) if (quantity) { priceSetQueryKnex.where("ma.min_quantity", "<=", quantity) priceSetQueryKnex.andWhere("ma.max_quantity", ">=", quantity) + } else { + priceSetQueryKnex.andWhere(function () { + this.andWhere("ma.min_quantity", "<=", "1").orWhereNull( + "ma.min_quantity" + ) + }) } return await priceSetQueryKnex diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index 101ad70055c79..ce623d79ac222 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -13,7 +13,15 @@ import { PricingTypes, RuleTypeDTO, } from "@medusajs/types" -import { PriceListType } from "@medusajs/utils" +import { + InjectManager, + InjectTransactionManager, + MedusaContext, + MedusaError, + PriceListType, + groupBy, + removeNullish, +} from "@medusajs/utils" import { Currency, @@ -42,15 +50,6 @@ import { PriceSetService, RuleTypeService, } from "@services" - -import { - groupBy, - InjectManager, - InjectTransactionManager, - MedusaContext, - MedusaError, - removeNullish, -} from "@medusajs/utils" import { joinerConfig } from "../joiner-config" import { CreatePriceListRuleValueDTO, PricingRepositoryService } from "../types" @@ -147,6 +146,7 @@ export default class PricingModuleService< pricingContext, sharedContext ) + const pricesSetPricesMap = groupBy(results, "price_set_id") const calculatedPrices = pricingFilters.id.map( @@ -155,8 +155,9 @@ export default class PricingModuleService< // which is prioritized by number_rules first for exact match and then deafult_priority of the rule_type // inject custom price selection here const prices = pricesSetPricesMap.get(priceSetId) || [] - const priceListPrice = prices?.find((p) => !!p.price_list_id) - const defaultPrice = prices?.find((p) => !!!p.price_list_id) + const priceListPrice = prices.find((p) => p.price_list_id) + + const defaultPrice = prices?.find((p) => !p.price_list_id) let calculatedPrice: PricingTypes.CalculatedPriceSetDTO = defaultPrice let originalPrice: PricingTypes.CalculatedPriceSetDTO = defaultPrice diff --git a/packages/product/integration-tests/__tests__/services/product-module-service/products.spec.ts b/packages/product/integration-tests/__tests__/services/product-module-service/products.spec.ts index abfbb7c579ff0..f2e4f8754b76b 100644 --- a/packages/product/integration-tests/__tests__/services/product-module-service/products.spec.ts +++ b/packages/product/integration-tests/__tests__/services/product-module-service/products.spec.ts @@ -201,6 +201,7 @@ describe("ProductModuleService products", function () { expect(createdVariant?.options).toHaveLength(1) expect(product.tags).toHaveLength(1) expect(product.variants).toHaveLength(2) + expect(product).toEqual( expect.objectContaining({ id: expect.any(String), diff --git a/packages/product/src/loaders/container.ts b/packages/product/src/loaders/container.ts index 085f8e21fa9f6..7375d3a9ef0c5 100644 --- a/packages/product/src/loaders/container.ts +++ b/packages/product/src/loaders/container.ts @@ -5,6 +5,7 @@ import { ProductCollectionRepository, ProductImageRepository, ProductOptionRepository, + ProductOptionValueRepository, ProductRepository, ProductTagRepository, ProductTypeRepository, @@ -17,6 +18,7 @@ import { ProductImageService, ProductModuleService, ProductOptionService, + ProductOptionValueService, ProductService, ProductTagService, ProductTypeService, @@ -48,6 +50,7 @@ export default async ({ productImageService: asClass(ProductImageService).singleton(), productTypeService: asClass(ProductTypeService).singleton(), productOptionService: asClass(ProductOptionService).singleton(), + productOptionValueService: asClass(ProductOptionValueService).singleton(), }) if (customRepositories) { @@ -69,6 +72,9 @@ function loadDefaultRepositories({ container }) { productTagRepository: asClass(ProductTagRepository).singleton(), productTypeRepository: asClass(ProductTypeRepository).singleton(), productOptionRepository: asClass(ProductOptionRepository).singleton(), + productOptionValueRepository: asClass( + ProductOptionValueRepository + ).singleton(), productVariantRepository: asClass(ProductVariantRepository).singleton(), }) } diff --git a/packages/product/src/migrations/Migration20230719100648.ts b/packages/product/src/migrations/Migration20230719100648.ts index a99311bc5bfd8..aa66d30890166 100644 --- a/packages/product/src/migrations/Migration20230719100648.ts +++ b/packages/product/src/migrations/Migration20230719100648.ts @@ -8,8 +8,11 @@ export class Migration20230719100648 extends Migration { this.addSql( 'create index IF NOT EXISTS "IDX_product_category_path" on "product_category" ("mpath");' ) + + this.addSql('DROP INDEX IF EXISTS "IDX_product_category_handle";') + this.addSql( - 'alter table "product_category" add constraint "IDX_product_category_handle" unique ("handle");' + 'alter table "product_category" ADD CONSTRAINT "IDX_product_category_handle" unique ("handle");' ) this.addSql( diff --git a/packages/product/src/models/index.ts b/packages/product/src/models/index.ts index 6017c491d7036..f3f6a304fabe7 100644 --- a/packages/product/src/models/index.ts +++ b/packages/product/src/models/index.ts @@ -5,4 +5,5 @@ export { default as ProductTag } from "./product-tag" export { default as ProductType } from "./product-type" export { default as ProductVariant } from "./product-variant" export { default as ProductOption } from "./product-option" +export { default as ProductOptionValue } from "./product-option-value" export { default as Image } from "./product-image" diff --git a/packages/product/src/repositories/index.ts b/packages/product/src/repositories/index.ts index 77e7f8a7a1079..b1f0ab1e37f1f 100644 --- a/packages/product/src/repositories/index.ts +++ b/packages/product/src/repositories/index.ts @@ -7,3 +7,4 @@ export { ProductCategoryRepository } from "./product-category" export { ProductImageRepository } from "./product-image" export { ProductTypeRepository } from "./product-type" export { ProductOptionRepository } from "./product-option" +export { ProductOptionValueRepository } from "./product-option-value" diff --git a/packages/product/src/repositories/product-option-value.ts b/packages/product/src/repositories/product-option-value.ts new file mode 100644 index 0000000000000..f2f3e10bd8416 --- /dev/null +++ b/packages/product/src/repositories/product-option-value.ts @@ -0,0 +1,114 @@ +import { Context, DAL } from "@medusajs/types" +import { + CreateProductOptionValueDTO, + UpdateProductOptionValueDTO, +} from "../types/services/product-option-value" + +import { DALUtils } from "@medusajs/utils" +import { FilterQuery as MikroFilterQuery } from "@mikro-orm/core/typings" +import { FindOptions as MikroOptions } from "@mikro-orm/core/drivers/IDatabaseDriver" +import { ProductOptionValue } from "@models" +import { SqlEntityManager } from "@mikro-orm/postgresql" + +export class ProductOptionValueRepository extends DALUtils.MikroOrmBaseRepository { + protected readonly manager_: SqlEntityManager + + constructor({ manager }: { manager: SqlEntityManager }) { + // @ts-ignore + // eslint-disable-next-line prefer-rest-params + super(...arguments) + this.manager_ = manager + } + + async find( + findOptions: DAL.FindOptions = { where: {} }, + context: Context = {} + ): Promise { + const manager = this.getActiveManager(context) + const findOptions_ = { ...findOptions } + + findOptions_.options ??= {} + + return await manager.find( + ProductOptionValue, + findOptions_.where as MikroFilterQuery, + findOptions_.options as MikroOptions + ) + } + + async upsert( + optionValues: (UpdateProductOptionValueDTO | CreateProductOptionValueDTO)[], + context: Context = {} + ): Promise { + const manager = this.getActiveManager(context) + + const optionValueIds: string[] = [] + + for (const optionValue of optionValues) { + if (optionValue.id) { + optionValueIds.push(optionValue.id) + } + } + + const existingOptionValues = await this.find( + { + where: { + id: { + $in: optionValueIds, + }, + }, + }, + context + ) + + const existingOptionValuesMap = new Map( + existingOptionValues.map<[string, ProductOptionValue]>((optionValue) => [ + optionValue.id, + optionValue, + ]) + ) + + const upsertedOptionValues: ProductOptionValue[] = [] + const optionValuesToCreate: ProductOptionValue[] = [] + const optionValuesToUpdate: ProductOptionValue[] = [] + + optionValues.forEach(({ option_id, ...optionValue }) => { + const existingOptionValue = optionValue.id + ? existingOptionValuesMap.get(optionValue.id) + : undefined + + if (optionValue.id && existingOptionValue) { + const updatedOptionValue = manager.assign(existingOptionValue, { + option: option_id, + ...optionValue, + }) + optionValuesToUpdate.push(updatedOptionValue) + return + } + + const newOptionValue = manager.create(ProductOptionValue, { + option: option_id, + variant: (optionValue as CreateProductOptionValueDTO).variant_id, + ...optionValue, + }) + optionValuesToCreate.push(newOptionValue) + }) + + if (optionValuesToCreate.length) { + manager.persist(optionValuesToCreate) + upsertedOptionValues.push(...optionValuesToCreate) + } + + if (optionValuesToUpdate.length) { + manager.persist(optionValuesToUpdate) + upsertedOptionValues.push(...optionValuesToUpdate) + } + + return upsertedOptionValues + } + + async delete(ids: string[], context: Context = {}): Promise { + const manager = this.getActiveManager(context) + await manager.nativeDelete(ProductOptionValue, { id: { $in: ids } }, {}) + } +} diff --git a/packages/product/src/services/index.ts b/packages/product/src/services/index.ts index 0d7ba770b164b..dc485567aae5c 100644 --- a/packages/product/src/services/index.ts +++ b/packages/product/src/services/index.ts @@ -7,3 +7,4 @@ export { default as ProductVariantService } from "./product-variant" export { default as ProductTypeService } from "./product-type" export { default as ProductOptionService } from "./product-option" export { default as ProductImageService } from "./product-image" +export { default as ProductOptionValueService } from "./product-option-value" diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index 547052b87a1a3..a74109e1ed9ab 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -16,6 +16,7 @@ import { ProductCategory, ProductCollection, ProductOption, + ProductOptionValue, ProductTag, ProductType, ProductVariant, @@ -24,6 +25,7 @@ import { ProductCategoryService, ProductCollectionService, ProductOptionService, + ProductOptionValueService, ProductService, ProductTagService, ProductTypeService, @@ -53,6 +55,8 @@ import { } from "../types/services/product" import { + arrayDifference, + groupBy, InjectManager, InjectTransactionManager, isDefined, @@ -68,6 +72,10 @@ import { joinerConfig, LinkableKeys, } from "./../joiner-config" +import { + CreateProductOptionValueDTO, + UpdateProductOptionValueDTO, +} from "../types/services/product-option-value" type InjectedDependencies = { baseRepository: DAL.RepositoryService @@ -79,6 +87,7 @@ type InjectedDependencies = { productImageService: ProductImageService productTypeService: ProductTypeService productOptionService: ProductOptionService + productOptionValueService: ProductOptionValueService eventBusModuleService?: IEventBusModuleService } @@ -90,7 +99,8 @@ export default class ProductModuleService< TProductCategory extends ProductCategory = ProductCategory, TProductImage extends Image = Image, TProductType extends ProductType = ProductType, - TProductOption extends ProductOption = ProductOption + TProductOption extends ProductOption = ProductOption, + TProductOptionValue extends ProductOptionValue = ProductOptionValue > implements ProductTypes.IProductModuleService { protected baseRepository_: DAL.RepositoryService @@ -108,6 +118,8 @@ export default class ProductModuleService< protected readonly productImageService_: ProductImageService protected readonly productTypeService_: ProductTypeService protected readonly productOptionService_: ProductOptionService + // eslint-disable-next-line max-len + protected readonly productOptionValueService_: ProductOptionValueService protected readonly eventBusModuleService_?: IEventBusModuleService constructor( @@ -121,6 +133,7 @@ export default class ProductModuleService< productImageService, productTypeService, productOptionService, + productOptionValueService, eventBusModuleService, }: InjectedDependencies, protected readonly moduleDeclaration: InternalModuleDeclaration @@ -134,6 +147,7 @@ export default class ProductModuleService< this.productImageService_ = productImageService this.productTypeService_ = productTypeService this.productOptionService_ = productOptionService + this.productOptionValueService_ = productOptionValueService this.eventBusModuleService_ = eventBusModuleService } @@ -231,6 +245,207 @@ export default class ProductModuleService< return [JSON.parse(JSON.stringify(variants)), count] } + async createVariants( + data: ProductTypes.CreateProductVariantDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const productOptionIds = data + .map((pv) => (pv.options || []).map((opt) => opt.option_id!)) + .flat() + + const productOptions = await this.listOptions( + { id: productOptionIds }, + {}, + sharedContext + ) + + const productOptionsMap = new Map( + productOptions.map((po) => [po.id, po]) + ) + + const productVariantsMap = new Map< + string, + ProductTypes.CreateProductVariantDTO[] + >() + + for (const productVariantData of data) { + productVariantData.options = productVariantData.options?.map((option) => { + const productOption = productOptionsMap.get(option.option_id!) + + return { + option: productOption?.id, + value: option.value, + } + }) + + const productVariants = productVariantsMap.get( + productVariantData.product_id! + ) + + if (productVariants) { + productVariants.push(productVariantData) + } else { + productVariantsMap.set(productVariantData.product_id!, [ + productVariantData, + ]) + } + } + + const productVariants = ( + await promiseAll( + [...productVariantsMap].map(async ([productId, variants]) => { + return await this.productVariantService_.create( + productId, + variants as unknown as ProductTypes.CreateProductVariantOnlyDTO[], + sharedContext + ) + }) + ) + ).flat() + + return productVariants as unknown as ProductTypes.ProductVariantDTO[] + } + + @InjectTransactionManager("baseRepository_") + async deleteVariants( + productVariantIds: string[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + await this.productVariantService_.delete(productVariantIds, sharedContext) + + await this.eventBusModuleService_?.emit( + productVariantIds.map((id) => ({ + eventName: ProductEvents.PRODUCT_DELETED, + data: { id }, + })) + ) + } + + @InjectManager("baseRepository_") + async updateVariants( + data: ProductTypes.UpdateProductVariantOnlyDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const productVariants = await this.updateVariants_(data, sharedContext) + + const updatedVariants = await this.baseRepository_.serialize< + ProductTypes.ProductVariantDTO[] + >(productVariants, { + populate: true, + }) + + return updatedVariants + } + + @InjectTransactionManager("baseRepository_") + protected async updateVariants_( + data: ProductTypes.UpdateProductVariantOnlyDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const variantIdsToUpdate = data.map(({ id }) => id) + const variants = await this.listVariants( + { id: variantIdsToUpdate }, + { relations: ["options", "options.option"] }, + sharedContext + ) + const variantsMap = new Map( + variants.map((variant) => [variant.id, variant]) + ) + + if (variants.length !== data.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Cannot update non-existing variants with ids: ${arrayDifference( + variantIdsToUpdate, + [...variantsMap.keys()] + ).join(", ")}` + ) + } + + const optionValuesToUpsert: ( + | CreateProductOptionValueDTO + | UpdateProductOptionValueDTO + )[] = [] + const optionsValuesToDelete: string[] = [] + + const toUpdate = data.map(({ id, options, ...rest }) => { + const variant = variantsMap.get(id)! + + const toUpdate: UpdateProductVariantDTO = { + id, + product_id: variant.product_id, + } + + if (options?.length) { + const optionIdToUpdateValueMap = new Map( + options.map(({ option, option_id, value }) => { + const computedOptionId = option_id ?? option.id ?? option + return [computedOptionId, value] + }) + ) + + for (const existingOptionValue of variant.options) { + if (!optionIdToUpdateValueMap.has(existingOptionValue.option.id)) { + optionsValuesToDelete.push(existingOptionValue.id) + + continue + } + + optionValuesToUpsert.push({ + id: existingOptionValue.id, + option_id: existingOptionValue.option.id, + value: optionIdToUpdateValueMap.get(existingOptionValue.option.id)!, + }) + optionIdToUpdateValueMap.delete(existingOptionValue.option.id) + } + + for (const [option_id, value] of optionIdToUpdateValueMap.entries()) { + optionValuesToUpsert.push({ + option_id, + value, + variant_id: id, + }) + } + } + + for (const [key, value] of Object.entries(rest)) { + if (variant[key] !== value) { + toUpdate[key] = value + } + } + + return toUpdate + }) + + const groups = groupBy(toUpdate, "product_id") + + const [, , productVariants]: [ + void, + TProductOptionValue[], + TProductVariant[][] + ] = await promiseAll([ + await this.productOptionValueService_.delete( + optionsValuesToDelete, + sharedContext + ), + await this.productOptionValueService_.upsert( + optionValuesToUpsert, + sharedContext + ), + await promiseAll( + [...groups.entries()].map(async ([product_id, update]) => { + return await this.productVariantService_.update( + product_id, + update.map(({ product_id, ...update }) => update), + sharedContext + ) + }) + ), + ]) + + return productVariants.flat() + } + @InjectManager("baseRepository_") async retrieveTag( tagId: string, @@ -1022,7 +1237,11 @@ export default class ProductModuleService< if (!productData.thumbnail && productData.images?.length) { productData.thumbnail = isString(productData.images[0]) ? (productData.images[0] as string) - : (productData.images[0] as { url: string }).url + : ( + productData.images[0] as { + url: string + } + ).url } if (productData.images?.length) { diff --git a/packages/product/src/services/product-option-value.ts b/packages/product/src/services/product-option-value.ts new file mode 100644 index 0000000000000..f72a9fb533ea1 --- /dev/null +++ b/packages/product/src/services/product-option-value.ts @@ -0,0 +1,44 @@ +import { ProductOptionValue } from "@models" +import { Context, DAL } from "@medusajs/types" +import { + ProductOptionRepository, + ProductOptionValueRepository, +} from "@repositories" +import { InjectTransactionManager, MedusaContext } from "@medusajs/utils" +import { + CreateProductOptionValueDTO, + UpdateProductOptionValueDTO, +} from "../types/services/product-option-value" + +type InjectedDependencies = { + productOptionValueRepository: DAL.RepositoryService +} + +export default class ProductOptionValueService< + TEntity extends ProductOptionValue = ProductOptionValue +> { + protected readonly productOptionValueRepository_: DAL.RepositoryService + + constructor({ productOptionValueRepository }: InjectedDependencies) { + this.productOptionValueRepository_ = + productOptionValueRepository as ProductOptionRepository + } + + @InjectTransactionManager("productOptionValueRepository_") + async delete( + ids: string[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return await this.productOptionValueRepository_.delete(ids, sharedContext) + } + + @InjectTransactionManager("productOptionValueRepository_") + async upsert( + data: (UpdateProductOptionValueDTO | CreateProductOptionValueDTO)[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await ( + this.productOptionValueRepository_ as ProductOptionValueRepository + ).upsert!(data, sharedContext)) as TEntity[] + } +} diff --git a/packages/product/src/services/product-variant.ts b/packages/product/src/services/product-variant.ts index de7a776f67f80..06d30a8f021f0 100644 --- a/packages/product/src/services/product-variant.ts +++ b/packages/product/src/services/product-variant.ts @@ -1,14 +1,14 @@ -import { Product, ProductVariant } from "@models" import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types" -import { ProductVariantRepository } from "@repositories" import { InjectManager, InjectTransactionManager, - isString, MedusaContext, ModulesSdkUtils, + isString, retrieveEntity, } from "@medusajs/utils" +import { Product, ProductVariant } from "@models" +import { ProductVariantRepository } from "@repositories" import { ProductVariantServiceTypes } from "../types/services" import ProductService from "./product" @@ -96,7 +96,7 @@ export default class ProductVariantService< if (isString(productOrId)) { product = await this.productService_.retrieve( productOrId, - {}, + { relations: ["variants"] }, sharedContext ) } @@ -105,6 +105,8 @@ export default class ProductVariantService< const data_ = [...data] data_.forEach((variant) => { + delete variant?.product_id + Object.assign(variant, { variant_rank: computedRank++, product, diff --git a/packages/product/src/types/services/product-option-value.ts b/packages/product/src/types/services/product-option-value.ts new file mode 100644 index 0000000000000..5d375dabc45ae --- /dev/null +++ b/packages/product/src/types/services/product-option-value.ts @@ -0,0 +1,14 @@ +export interface UpdateProductOptionValueDTO { + id: string + value: string + option_id: string + metadata?: Record | null +} + +export interface CreateProductOptionValueDTO { + id?: string + value: string + option_id: string + variant_id: string + metadata?: Record | null +} diff --git a/packages/product/src/types/services/product-variant.ts b/packages/product/src/types/services/product-variant.ts index 1c7a90f95f105..0f4dedd361f63 100644 --- a/packages/product/src/types/services/product-variant.ts +++ b/packages/product/src/types/services/product-variant.ts @@ -2,6 +2,7 @@ import { CreateProductVariantOptionDTO } from "@medusajs/types" export interface UpdateProductVariantDTO { id: string + product_id: string title?: string sku?: string barcode?: string @@ -18,6 +19,6 @@ export interface UpdateProductVariantDTO { length?: number height?: number width?: number - options?: CreateProductVariantOptionDTO[] + options?: (CreateProductVariantOptionDTO & { id?: string })[] metadata?: Record } diff --git a/packages/types/src/pricing/common/money-amount.ts b/packages/types/src/pricing/common/money-amount.ts index 72e58d2e9a74d..160abead7bcb5 100644 --- a/packages/types/src/pricing/common/money-amount.ts +++ b/packages/types/src/pricing/common/money-amount.ts @@ -36,8 +36,6 @@ export interface MoneyAmountDTO { max_quantity?: number /** * The details of the relation between the money amount and its associated price set. - * - * @expandable */ price_set_money_amount?: PriceSetMoneyAmountDTO } diff --git a/packages/types/src/pricing/common/price-rule.ts b/packages/types/src/pricing/common/price-rule.ts index 5b22cbe9e96a8..738d4b3d885d7 100644 --- a/packages/types/src/pricing/common/price-rule.ts +++ b/packages/types/src/pricing/common/price-rule.ts @@ -4,7 +4,7 @@ import { RuleTypeDTO } from "./rule-type" /** * @interface - * + * * A price rule's data. */ export interface PriceRuleDTO { @@ -18,7 +18,6 @@ export interface PriceRuleDTO { price_set_id: string /** * The associated price set. - * * @expandable */ price_set: PriceSetDTO @@ -28,17 +27,10 @@ export interface PriceRuleDTO { rule_type_id: string /** * The associated rule type. - * + * * @expandable */ rule_type: RuleTypeDTO - /** - * @ignore - * @privateRemarks - * - * Behavior behind this property is not implemented yet. - */ - is_dynamic: boolean /** * The value of the price rule. */ @@ -58,9 +50,9 @@ export interface PriceRuleDTO { } /** - * + * * @interface - * + * * A price rule to create. */ export interface CreatePriceRuleDTO { @@ -76,13 +68,6 @@ export interface CreatePriceRuleDTO { * The ID of the associated rule type. */ rule_type_id: string - /** - * @ignore - * @privateRemarks - * - * Behavior behind this property is not implemented yet. - */ - is_dynamic?: boolean /** * The value of the price rule. */ @@ -92,22 +77,15 @@ export interface CreatePriceRuleDTO { } /** - * + * * @interface - * + * * The data to update in a price rule. The `id` is used to identify which money amount to update. */ export interface UpdatePriceRuleDTO { id: string price_set_id?: string rule_type_id?: string - /** - * @ignore - * @privateRemark - * - * Behavior behind this property is not implemented yet. - */ - is_dynamic?: boolean /** * The value of the price rule. */ @@ -128,7 +106,6 @@ export interface UpdatePriceRuleDTO { /** * @interface - * * Filters to apply on price rules. */ export interface FilterablePriceRuleProps diff --git a/packages/types/src/product/common.ts b/packages/types/src/product/common.ts index 27184f1d79d95..7f44de05f9445 100644 --- a/packages/types/src/product/common.ts +++ b/packages/types/src/product/common.ts @@ -13,7 +13,7 @@ export enum ProductStatus { /** * @interface - * + * * A product's data. */ export interface ProductDTO { @@ -83,43 +83,43 @@ export interface ProductDTO { material?: string | null /** * The associated product collection. - * + * * @expandable */ collection: ProductCollectionDTO /** * The associated product categories. - * + * * @expandable */ categories?: ProductCategoryDTO[] | null /** * The associated product type. - * + * * @expandable */ type: ProductTypeDTO[] /** * The associated product tags. - * + * * @expandable */ tags: ProductTagDTO[] /** * The associated product variants. - * + * * @expandable */ variants: ProductVariantDTO[] /** * The associated product options. - * + * * @expandable */ options: ProductOptionDTO[] /** * The associated product images. - * + * * @expandable */ images: ProductImageDTO[] @@ -152,7 +152,7 @@ export interface ProductDTO { /** * @interface - * + * * A product variant's data. */ export interface ProductVariantDTO { @@ -226,17 +226,17 @@ export interface ProductVariantDTO { width?: number | null /** * The associated product options. - * + * * @expandable */ - options: ProductOptionValueDTO + options: ProductOptionValueDTO[] /** * Holds custom data in key-value pairs. */ metadata?: Record | null /** * The associated product. - * + * * @expandable */ product: ProductDTO @@ -264,7 +264,7 @@ export interface ProductVariantDTO { /** * @interface - * + * * A product category's data. */ export interface ProductCategoryDTO { @@ -298,13 +298,13 @@ export interface ProductCategoryDTO { rank?: number /** * The associated parent category. - * + * * @expandable */ parent_category?: ProductCategoryDTO /** * The associated child categories. - * + * * @expandable */ category_children: ProductCategoryDTO[] @@ -320,7 +320,7 @@ export interface ProductCategoryDTO { /** * @interface - * + * * A product category to create. */ export interface CreateProductCategoryDTO { @@ -356,7 +356,7 @@ export interface CreateProductCategoryDTO { /** * @interface - * + * * The data to update in a product category. */ export interface UpdateProductCategoryDTO { @@ -392,7 +392,7 @@ export interface UpdateProductCategoryDTO { /** * @interface - * + * * A product tag's data. */ export interface ProductTagDTO { @@ -410,7 +410,7 @@ export interface ProductTagDTO { metadata?: Record | null /** * The associated products. - * + * * @expandable */ products?: ProductDTO[] @@ -418,7 +418,7 @@ export interface ProductTagDTO { /** * @interface - * + * * A product collection's data. */ export interface ProductCollectionDTO { @@ -444,7 +444,7 @@ export interface ProductCollectionDTO { deleted_at?: string | Date /** * The associated products. - * + * * @expandable */ products?: ProductDTO[] @@ -452,7 +452,7 @@ export interface ProductCollectionDTO { /** * @interface - * + * * A product type's data. */ export interface ProductTypeDTO { @@ -476,9 +476,9 @@ export interface ProductTypeDTO { /** * @interface - * + * * A product option's data. - * + * */ export interface ProductOptionDTO { /** @@ -491,13 +491,13 @@ export interface ProductOptionDTO { title: string /** * The associated product. - * + * * @expandable */ product: ProductDTO /** * The associated product option values. - * + * * @expandable */ values: ProductOptionValueDTO[] @@ -513,8 +513,13 @@ export interface ProductOptionDTO { /** * @interface - * + * * The product image's data. + * + * @prop id - The ID of the product image. + * @prop url - The URL of the product image. + * @prop metadata - Holds custom data in key-value pairs. + * @prop deleted_at - When the product image was deleted. */ export interface ProductImageDTO { /** @@ -537,8 +542,15 @@ export interface ProductImageDTO { /** * @interface - * + * * The product option value's data. + * + * @prop id - The ID of the product option value. + * @prop value - The value of the product option value. + * @prop option - The associated product option. It may only be available if the `option` relation is expanded. + * @prop variant - The associated product variant. It may only be available if the `variant` relation is expanded. + * @prop metadata - Holds custom data in key-value pairs. + * @prop deleted_at - When the product option value was deleted. */ export interface ProductOptionValueDTO { /** @@ -551,13 +563,13 @@ export interface ProductOptionValueDTO { value: string /** * The associated product option. - * + * * @expandable */ option: ProductOptionDTO /** * The associated product variant. - * + * * @expandable */ variant: ProductVariantDTO @@ -573,8 +585,15 @@ export interface ProductOptionValueDTO { /** * @interface - * + * * The filters to apply on retrieved products. + * + * @prop q - Search through the products' attributes, such as titles and descriptions, using this search term. + * @prop handle - The handles to filter products by. + * @prop id - The IDs to filter products by. + * @prop tags - Filters on a product's tags. + * @prop categories - Filters on a product's categories. + * @prop collection_id - Filters a product by its associated collections. */ export interface FilterableProductProps extends BaseFilterable { @@ -593,7 +612,7 @@ export interface FilterableProductProps /** * Filters on a product's tags. */ - tags?: { + tags?: { /** * Values to filter product tags by. */ @@ -628,8 +647,11 @@ export interface FilterableProductProps /** * @interface - * + * * The filters to apply on retrieved product tags. + * + * @prop id - The IDs to filter product tags by. + * @prop value - The value to filter product tags by. */ export interface FilterableProductTagProps extends BaseFilterable { @@ -645,8 +667,11 @@ export interface FilterableProductTagProps /** * @interface - * + * * The filters to apply on retrieved product types. + * + * @prop id - The IDs to filter product types by. + * @prop value - The value to filter product types by. */ export interface FilterableProductTypeProps extends BaseFilterable { @@ -662,8 +687,12 @@ export interface FilterableProductTypeProps /** * @interface - * + * * The filters to apply on retrieved product options. + * + * @prop id - The IDs to filter product options by. + * @prop title - The titles to filter product options by. + * @prop product_id - Filter the product options by their associated products' IDs. */ export interface FilterableProductOptionProps extends BaseFilterable { @@ -683,8 +712,11 @@ export interface FilterableProductOptionProps /** * @interface - * + * * The filters to apply on retrieved product collections. + * + * @prop id - The IDs to filter product collections by. + * @prop title - The title to filter product collections by. */ export interface FilterableProductCollectionProps extends BaseFilterable { @@ -704,8 +736,13 @@ export interface FilterableProductCollectionProps /** * @interface - * + * * The filters to apply on retrieved product variants. + * + * @prop id - The IDs to filter product variants by. + * @prop sku - The SKUs to filter product variants by. + * @prop product_id - Filter the product variants by their associated products' IDs. + * @prop options - Filter product variants by their associated options. */ export interface FilterableProductVariantProps extends BaseFilterable { @@ -724,7 +761,7 @@ export interface FilterableProductVariantProps /** * Filter product variants by their associated options. */ - options?: { + options?: { /** * IDs to filter options by. */ @@ -734,8 +771,16 @@ export interface FilterableProductVariantProps /** * @interface - * + * * The filters to apply on retrieved product categories. + * + * @prop id - The IDs to filter product categories by. + * @prop name - The names to filter product categories by. + * @prop parent_category_id - Filter product categories by their parent category's ID. + * @prop handle - The handles to filter product categories by. + * @prop is_active - Filter product categories by whether they're active. + * @prop is_internal - Filter product categories by whether they're internal. + * @prop include_descendants_tree - Whether to include children of retrieved product categories. */ export interface FilterableProductCategoryProps extends BaseFilterable { @@ -771,8 +816,13 @@ export interface FilterableProductCategoryProps /** * @interface - * + * * A product collection to create. + * + * @prop title - The product collection's title. + * @prop handle - The product collection's handle. If not provided, the value of this attribute is set to the slug version of the title. + * @prop products - The products to associate with the collection. + * @prop metadata - Holds custom data in key-value pairs. */ export interface CreateProductCollectionDTO { /** @@ -795,7 +845,7 @@ export interface CreateProductCollectionDTO { /** * @interface - * + * * The data to update in a product collection. The `id` is used to identify which product collection to update. */ export interface UpdateProductCollectionDTO { @@ -827,7 +877,7 @@ export interface UpdateProductCollectionDTO { /** * @interface - * + * * A product type to create. */ export interface CreateProductTypeDTO { @@ -852,7 +902,7 @@ export interface UpsertProductTypeDTO { /** * @interface - * + * * The data to update in a product type. The `id` is used to identify which product type to update. */ export interface UpdateProductTypeDTO { @@ -872,7 +922,7 @@ export interface UpdateProductTypeDTO { /** * @interface - * + * * A product tag to create. */ export interface CreateProductTagDTO { @@ -888,9 +938,9 @@ export interface UpsertProductTagDTO { } /** - * + * * @interface - * + * * The data to update in a product tag. The `id` is used to identify which product tag to update. */ export interface UpdateProductTagDTO { @@ -906,7 +956,7 @@ export interface UpdateProductTagDTO { /** * @interface - * + * * A product option to create. */ export interface CreateProductOptionDTO { @@ -928,7 +978,7 @@ export interface UpdateProductOptionDTO { /** * @interface - * + * * A product variant option to create. */ export interface CreateProductVariantOptionDTO { @@ -936,14 +986,20 @@ export interface CreateProductVariantOptionDTO { * The value of a product variant option. */ value: string + + option_id?: string } /** * @interface - * + * * A product variant to create. */ export interface CreateProductVariantDTO { + /** + * The id of the product + */ + product_id?: string /** * The tile of the product variant. */ @@ -1020,7 +1076,7 @@ export interface CreateProductVariantDTO { /** * @interface - * + * * The data to update in a product variant. The `id` is used to identify which product variant to update. */ export interface UpdateProductVariantDTO { @@ -1104,7 +1160,7 @@ export interface UpdateProductVariantDTO { /** * @interface - * + * * A product to create. */ export interface CreateProductDTO { @@ -1214,7 +1270,7 @@ export interface CreateProductDTO { /** * @interface - * + * * The data to update in a product. The `id` is used to identify which product to update. */ export interface UpdateProductDTO { @@ -1352,6 +1408,7 @@ export interface CreateProductOnlyDTO { } export interface CreateProductVariantOnlyDTO { + product_id?: string title: string sku?: string barcode?: string diff --git a/packages/types/src/product/service.ts b/packages/types/src/product/service.ts index 14a67c4260abb..00b3320fe187a 100644 --- a/packages/types/src/product/service.ts +++ b/packages/types/src/product/service.ts @@ -5,6 +5,7 @@ import { CreateProductOptionDTO, CreateProductTagDTO, CreateProductTypeDTO, + CreateProductVariantDTO, FilterableProductCategoryProps, FilterableProductCollectionProps, FilterableProductOptionProps, @@ -25,12 +26,13 @@ import { UpdateProductOptionDTO, UpdateProductTagDTO, UpdateProductTypeDTO, + UpdateProductVariantDTO, } from "./common" +import { RestoreReturn, SoftDeleteReturn } from "../dal" +import { Context } from "../shared-context" import { FindConfig } from "../common" -import { RestoreReturn, SoftDeleteReturn } from "../dal" import { ModuleJoinerConfig } from "../modules-sdk" -import { Context } from "../shared-context" export interface IProductModuleService { /** @@ -40,45 +42,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a product by its ID - * - * @param {string} productId - The ID of the product to retrieve. - * @param {FindConfig} config - + * + * @param {string} productId - The ID of the product to retrieve. + * @param {FindConfig} config - * The configurations determining how the product is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product. - * + * * @example * A simple example that retrieves a product by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProduct (id: string) { * const productModule = await initializeProductModule() - * + * * const product = await productModule.retrieve(id) - * + * * // do something with the product or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProduct (id: string) { * const productModule = await initializeProductModule() - * + * * const product = await productModule.retrieve(id, { * relations: ["categories"] * }) - * + * * // do something with the product or return it * } * ``` @@ -91,85 +93,85 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of price sets based on optional filters and configuration. - * + * * @param {FilterableProductProps} filters - The filters to apply on the retrieved products. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the products are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of products. - * + * * @example * To retrieve a list of products using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.list({ * id: ids * }) - * + * * // do something with the products or return them * } * ``` - * + * * To specify relations that should be retrieved within the products: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.list({ * id: ids * }, { * relations: ["categories"] * }) - * + * * // do something with the products or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.list({ * id: ids * }, { * relations: ["categories"], - * skip, + * skip, * take * }) - * + * * // do something with the products or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.list({ * $and: [ * { @@ -181,10 +183,10 @@ export interface IProductModuleService { * ] * }, { * relations: ["categories"], - * skip, + * skip, * take * }) - * + * * // do something with the products or return them * } * ``` @@ -197,85 +199,85 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of products along with the total count of available products satisfying the provided filters. - * + * * @param {FilterableProductProps} filters - The filters to apply on the retrieved products. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the products are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of products along with the total count. - * + * * @example * To retrieve a list of products using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [products, count] = await productModule.listAndCount({ * id: ids * }) - * + * * // do something with the products or return them * } * ``` - * + * * To specify relations that should be retrieved within the products: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [products, count] = await productModule.listAndCount({ * id: ids * }, { * relations: ["categories"] * }) - * + * * // do something with the products or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [products, count] = await productModule.listAndCount({ * id: ids * }, { * relations: ["categories"], - * skip, + * skip, * take * }) - * + * * // do something with the products or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProducts (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [products, count] = await productModule.listAndCount({ * $and: [ * { @@ -287,10 +289,10 @@ export interface IProductModuleService { * ] * }, { * relations: ["categories"], - * skip, + * skip, * take * }) - * + * * // do something with the products or return them * } * ``` @@ -303,45 +305,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a tag by its ID. - * - * @param {string} tagId - The ID of the tag to retrieve. - * @param {FindConfig} config - + * + * @param {string} tagId - The ID of the tag to retrieve. + * @param {FindConfig} config - * The configurations determining how the product tag is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product tag. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product tag. - * + * * @example * A simple example that retrieves a product tag by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagId: string) { * const productModule = await initializeProductModule() - * + * * const productTag = await productModule.retrieveTag(tagId) - * + * * // do something with the product tag or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagId: string) { * const productModule = await initializeProductModule() - * + * * const productTag = await productModule.retrieveTag(tagId, { * relations: ["products"] * }) - * + * * // do something with the product tag or return it * } * ``` @@ -354,63 +356,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of tags based on optional filters and configuration. - * + * * @param {FilterableProductTagProps} filters - The filters applied on the retrieved product tags. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product tags are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product tag. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product tags. - * + * * @example * To retrieve a list of product tags using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[]) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.listTags({ * id: tagIds * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * To specify relations that should be retrieved within the product tags: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[]) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.listTags({ * id: tagIds * }, { * relations: ["products"] * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.listTags({ * id: tagIds * }, { @@ -418,21 +420,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[], value: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.listTags({ * $and: [ * { @@ -447,7 +449,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product tags or return them * } * ``` @@ -460,63 +462,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product tags along with the total count of available product tags satisfying the provided filters. - * + * * @param {FilterableProductTagProps} filters - The filters applied on the retrieved product tags. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product tags are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product tag. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductTagDTO[], number]>} The list of product tags along with the total count. - * + * * @example * To retrieve a list of product tags using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[]) { * const productModule = await initializeProductModule() - * + * * const [productTags, count] = await productModule.listAndCountTags({ * id: tagIds * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * To specify relations that should be retrieved within the product tags: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[]) { * const productModule = await initializeProductModule() - * + * * const [productTags, count] = await productModule.listAndCountTags({ * id: tagIds * }, { * relations: ["products"] * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productTags, count] = await productModule.listAndCountTags({ * id: tagIds * }, { @@ -524,21 +526,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product tags or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTag (tagIds: string[], value: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productTags, count] = await productModule.listAndCountTags({ * $and: [ * { @@ -553,7 +555,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product tags or return them * } * ``` @@ -566,25 +568,25 @@ export interface IProductModuleService { /** * This method is used to create product tags. - * + * * @param {CreateProductTagDTO[]} data - The product tags to create. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product tags. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createProductTags (values: string[]) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.createTags( * values.map((value) => ({ * value * })) * ) - * + * * // do something with the product tags or return them * } */ @@ -595,26 +597,26 @@ export interface IProductModuleService { /** * This method is used to update existing product tags. - * + * * @param {UpdateProductTagDTO[]} data - The product tags to be updated, each having the attributes that should be updated in a product tag. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of updated product tags. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateProductTag (id: string, value: string) { * const productModule = await initializeProductModule() - * + * * const productTags = await productModule.updateTags([ * { * id, * value * } * ]) - * + * * // do something with the product tags or return them * } */ @@ -625,66 +627,66 @@ export interface IProductModuleService { /** * This method is used to delete product tags by their ID. - * + * * @param {string[]} productTagIds - The IDs of the product tags to be deleted. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the product tags are successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteProductTags (ids: string[]) { * const productModule = await initializeProductModule() - * + * * await productModule.deleteTags(ids) - * + * * } */ deleteTags(productTagIds: string[], sharedContext?: Context): Promise /** * This method is used to retrieve a product type by its ID. - * + * * @param {string} typeId - The ID of the product type to retrieve. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product type is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product type. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product type. - * + * * @example * A simple example that retrieves a product type by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductType (id: string) { * const productModule = await initializeProductModule() - * + * * const productType = await productModule.retrieveType(id) - * + * * // do something with the product type or return it * } * ``` - * + * * To specify attributes that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductType (id: string) { * const productModule = await initializeProductModule() - * + * * const productType = await productModule.retrieveType(id, { * select: ["value"] * }) - * + * * // do something with the product type or return it * } * ``` @@ -697,63 +699,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product types based on optional filters and configuration. - * + * * @param {FilterableProductTypeProps} filters - The filters to apply on the retrieved product types. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product types are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product type. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product types. - * + * * @example * To retrieve a list of product types using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.listTypes({ * id: ids * }) - * + * * // do something with the product types or return them * } * ``` - * + * * To specify attributes that should be retrieved within the product types: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.listTypes({ * id: ids * }, { * select: ["value"] * }) - * + * * // do something with the product types or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.listTypes({ * id: ids * }, { @@ -761,21 +763,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product types or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[], value: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.listTypes({ * $and: [ * { @@ -790,7 +792,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product types or return them * } * ``` @@ -803,63 +805,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product types along with the total count of available product types satisfying the provided filters. - * + * * @param {FilterableProductTypeProps} filters - The filters to be applied on the retrieved product type. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product types are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product type. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductTypeDTO[], number]>} The list of product types along with their total count. - * + * * @example * To retrieve a list of product types using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [productTypes, count] = await productModule.listAndCountTypes({ * id: ids * }) - * + * * // do something with the product types or return them * } * ``` - * + * * To specify attributes that should be retrieved within the product types: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [productTypes, count] = await productModule.listAndCountTypes({ * id: ids * }, { * select: ["value"] * }) - * + * * // do something with the product types or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productTypes, count] = await productModule.listAndCountTypes({ * id: ids * }, { @@ -867,21 +869,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product types or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductTypes (ids: string[], value: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productTypes, count] = await productModule.listAndCountTypes({ * $and: [ * { @@ -896,7 +898,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product types or return them * } * ``` @@ -909,25 +911,25 @@ export interface IProductModuleService { /** * This method is used to create a product type. - * + * * @param {CreateProductTypeDTO[]} data - The product types to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @return {Promise} The list of created product types. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createProductType (value: string) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.createTypes([ * { * value * } * ]) - * + * * // do something with the product types or return them * } */ @@ -938,26 +940,26 @@ export interface IProductModuleService { /** * This method is used to update a product type - * + * * @param {UpdateProductTypeDTO[]} data - The product types to be updated, each having the attributes that should be updated in the product type. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of updated product types. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateProductType (id: string, value: string) { * const productModule = await initializeProductModule() - * + * * const productTypes = await productModule.updateTypes([ * { * id, * value * } * ]) - * + * * // do something with the product types or return them * } */ @@ -968,19 +970,19 @@ export interface IProductModuleService { /** * This method is used to delete a product type. - * + * * @param {string[]} productTypeIds - The IDs of the product types to be deleted. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the product types are successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteProductTypes (ids: string[]) { * const productModule = await initializeProductModule() - * + * * await productModule.deleteTypes(ids) * } */ @@ -988,45 +990,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a product option by its ID. - * + * * @param {string} optionId - The ID of the product option to retrieve. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product option is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product option. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product option. - * + * * @example * A simple example that retrieves a product option by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOption (id: string) { * const productModule = await initializeProductModule() - * + * * const productOption = await productModule.retrieveOption(id) - * + * * // do something with the product option or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOption (id: string) { * const productModule = await initializeProductModule() - * + * * const productOption = await productModule.retrieveOption(id, { * relations: ["product"] * }) - * + * * // do something with the product option or return it * } * ``` @@ -1039,63 +1041,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product options based on optional filters and configuration. - * + * * @param {FilterableProductOptionProps} filters - The filters applied on the retrieved product options. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product options are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product option. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product options. - * + * * @example * To retrieve a list of product options using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.listOptions({ * id: ids * }) - * + * * // do something with the product options or return them * } * ``` - * + * * To specify relations that should be retrieved within the product types: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.listOptions({ * id: ids * }, { * relations: ["product"] * }) - * + * * // do something with the product options or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.listOptions({ * id: ids * }, { @@ -1103,21 +1105,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product options or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.listOptions({ * $and: [ * { @@ -1132,7 +1134,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product options or return them * } * ``` @@ -1145,63 +1147,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product options along with the total count of available product options satisfying the provided filters. - * + * * @param {FilterableProductOptionProps} filters - The filters applied on the retrieved product options. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product options are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product option. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductOptionDTO[], number]>} The list of product options along with the total count. - * + * * @example * To retrieve a list of product options using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [productOptions, count] = await productModule.listAndCountOptions({ * id: ids * }) - * + * * // do something with the product options or return them * } * ``` - * + * * To specify relations that should be retrieved within the product types: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [productOptions, count] = await productModule.listAndCountOptions({ * id: ids * }, { * relations: ["product"] * }) - * + * * // do something with the product options or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productOptions, count] = await productModule.listAndCountOptions({ * id: ids * }, { @@ -1209,21 +1211,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product options or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductOptions (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [productOptions, count] = await productModule.listAndCountOptions({ * $and: [ * { @@ -1238,7 +1240,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product options or return them * } * ``` @@ -1251,26 +1253,26 @@ export interface IProductModuleService { /** * This method is used to create product options. - * + * * @param {CreateProductOptionDTO[]} data - The product options to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {ProductOptionDTO[]} The list of created product options. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createProductOption (title: string, productId: string) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.createOptions([ * { * title, * product_id: productId * } * ]) - * + * * // do something with the product options or return them * } */ @@ -1281,26 +1283,26 @@ export interface IProductModuleService { /** * This method is used to update existing product options. - * + * * @param {UpdateProductOptionDTO[]} data - The product options to be updated, each holding the attributes that should be updated in the product option. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {ProductOptionDTO[]} The list of updated product options. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateProductOption (id: string, title: string) { * const productModule = await initializeProductModule() - * + * * const productOptions = await productModule.updateOptions([ * { * id, * title * } * ]) - * + * * // do something with the product options or return them * } */ @@ -1311,19 +1313,19 @@ export interface IProductModuleService { /** * This method is used to delete a product option. - * + * * @param {string[]} productOptionIds - The IDs of the product options to delete. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the product options are successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteProductOptions (ids: string[]) { * const productModule = await initializeProductModule() - * + * * await productModule.deleteOptions(ids) * } */ @@ -1334,45 +1336,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a product variant by its ID. - * + * * @param {string} productVariantId - The ID of the product variant to retrieve. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product variant is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product variant. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product variant. - * + * * @example * A simple example that retrieves a product variant by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariant (id: string) { * const productModule = await initializeProductModule() - * + * * const variant = await productModule.retrieveVariant(id) - * + * * // do something with the product variant or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariant (id: string) { * const productModule = await initializeProductModule() - * + * * const variant = await productModule.retrieveVariant(id, { * relations: ["options"] * }) - * + * * // do something with the product variant or return it * } * ``` @@ -1385,63 +1387,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product variants based on optional filters and configuration. - * + * * @param {FilterableProductVariantProps} filters - The filters applied on the retrieved product variants. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product variants are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product variant. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product variants. - * + * * @example * To retrieve a list of product variants using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const variants = await productModule.listVariants({ * id: ids * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * To specify relations that should be retrieved within the product variants: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const variants = await productModule.listVariants({ * id: ids * }, { * relations: ["options"] * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const variants = await productModule.listVariants({ * id: ids * }, { @@ -1449,21 +1451,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[], sku: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const variants = await productModule.listVariants({ * $and: [ * { @@ -1478,7 +1480,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product variants or return them * } * ``` @@ -1489,65 +1491,98 @@ export interface IProductModuleService { sharedContext?: Context ): Promise + updateVariants( + data: UpdateProductVariantDTO[], + sharedContext?: Context + ): Promise + + createVariants( + data: CreateProductVariantDTO[], + sharedContext?: Context + ): Promise + + /** + * This method is used to delete ProductVariant. This method will completely remove the ProductVariant and they can no longer be accessed or retrieved. + * + * @param {string[]} productVariantIds - The IDs of the ProductVariant to be deleted. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} Resolves when the ProductVariant are successfully deleted. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function deleteProducts (ids: string[]) { + * const productModule = await initializeProductModule() + * + * await productModule.deleteVariants(ids) + * } + */ + deleteVariants( + productVariantIds: string[], + sharedContext?: Context + ): Promise + /** * This method is used to retrieve a paginated list of product variants along with the total count of available product variants satisfying the provided filters. - * + * * @param {FilterableProductVariantProps} filters - The filters applied on the retrieved product variants. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product variants are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product variant. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductVariantDTO[], number]>} The list of product variants along with their total count. - * + * * @example * To retrieve a list of product variants using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [variants, count] = await productModule.listAndCountVariants({ * id: ids * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * To specify relations that should be retrieved within the product variants: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [variants, count] = await productModule.listAndCountVariants({ * id: ids * }, { * relations: ["options"] * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [variants, count] = await productModule.listAndCountVariants({ * id: ids * }, { @@ -1555,21 +1590,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product variants or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveProductVariants (ids: string[], sku: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [variants, count] = await productModule.listAndCountVariants({ * $and: [ * { @@ -1584,7 +1619,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product variants or return them * } * ``` @@ -1597,45 +1632,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a product collection by its ID. - * + * * @param {string} productCollectionId - The ID of the product collection to retrieve. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product collection is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product collection. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product collection. - * + * * @example * A simple example that retrieves a product collection by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollection (id: string) { * const productModule = await initializeProductModule() - * + * * const collection = await productModule.retrieveCollection(id) - * + * * // do something with the product collection or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollection (id: string) { * const productModule = await initializeProductModule() - * + * * const collection = await productModule.retrieveCollection(id, { * relations: ["products"] * }) - * + * * // do something with the product collection or return it * } * ``` @@ -1648,63 +1683,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product collections based on optional filters and configuration. - * + * * @param {FilterableProductCollectionProps} filters - The filters applied on the retrieved product collections. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product collections are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product collection. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product collections. - * + * * @example * To retrieve a list of product collections using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.listCollections({ * id: ids * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * To specify relations that should be retrieved within the product collections: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.listCollections({ * id: ids * }, { * relations: ["products"] * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.listCollections({ * id: ids * }, { @@ -1712,21 +1747,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.listCollections({ * $and: [ * { @@ -1741,7 +1776,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product collections or return them * } * ``` @@ -1754,63 +1789,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product collections along with the total count of available product collections satisfying the provided filters. - * + * * @param {FilterableProductCollectionProps} filters - The filters applied on the retrieved product collections. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product collections are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product collection. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductCollectionDTO[], number]>} The list of product collections along with the total count. - * + * * @example * To retrieve a list of product collections using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [collections, count] = await productModule.listAndCountCollections({ * id: ids * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * To specify relations that should be retrieved within the product collections: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [collections, count] = await productModule.listAndCountCollections({ * id: ids * }, { * relations: ["products"] * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [collections, count] = await productModule.listAndCountCollections({ * id: ids * }, { @@ -1818,21 +1853,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product collections or return them * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCollections (ids: string[], title: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [collections, count] = await productModule.listAndCountCollections({ * $and: [ * { @@ -1847,7 +1882,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product collections or return them * } * ``` @@ -1860,28 +1895,28 @@ export interface IProductModuleService { /** * This method is used to create product collections. - * + * * @param {CreateProductCollectionDTO[]} data - The product collections to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of created product collections. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createCollection (title: string) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.createCollections([ * { * title * } * ]) - * + * * // do something with the product collections or return them * } - * + * */ createCollections( data: CreateProductCollectionDTO[], @@ -1890,29 +1925,29 @@ export interface IProductModuleService { /** * This method is used to update existing product collections. - * + * * @param {UpdateProductCollectionDTO[]} data - The product collections to be updated, each holding the attributes that should be updated in the product collection. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of updated product collections. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateCollection (id: string, title: string) { * const productModule = await initializeProductModule() - * + * * const collections = await productModule.updateCollections([ * { * id, * title * } * ]) - * + * * // do something with the product collections or return them * } - * + * */ updateCollections( data: UpdateProductCollectionDTO[], @@ -1921,22 +1956,22 @@ export interface IProductModuleService { /** * This method is used to delete collections by their ID. - * + * * @param {string[]} productCollectionIds - The IDs of the product collections to be updated. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the product options are successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteCollection (ids: string[]) { * const productModule = await initializeProductModule() - * + * * await productModule.deleteCollections(ids) * } - * + * */ deleteCollections( productCollectionIds: string[], @@ -1945,45 +1980,45 @@ export interface IProductModuleService { /** * This method is used to retrieve a product category by its ID. - * + * * @param {string} productCategoryId - The ID of the product category to retrieve. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product category is retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product category. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The retrieved product category. - * + * * @example * A simple example that retrieves a product category by its ID: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategory (id: string) { * const productModule = await initializeProductModule() - * + * * const category = await productModule.retrieveCategory(id) - * + * * // do something with the product category or return it * } * ``` - * + * * To specify relations that should be retrieved: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategory (id: string) { * const productModule = await initializeProductModule() - * + * * const category = await productModule.retrieveCategory(id, { * relations: ["parent_category"] * }) - * + * * // do something with the product category or return it * } * ``` @@ -1996,63 +2031,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product categories based on optional filters and configuration. - * + * * @param {FilterableProductCategoryProps} filters - The filters to be applied on the retrieved product categories. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product categories are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product category. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of product categories. - * + * * @example * To retrieve a list of product categories using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const categories = await productModule.listCategories({ * id: ids * }) - * + * * // do something with the product category or return it * } * ``` - * + * * To specify relations that should be retrieved within the product categories: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const categories = await productModule.listCategories({ * id: ids * }, { * relations: ["parent_category"] * }) - * + * * // do something with the product category or return it * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const categories = await productModule.listCategories({ * id: ids * }, { @@ -2060,21 +2095,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product category or return it * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[], name: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const categories = await productModule.listCategories({ * $or: [ * { @@ -2089,7 +2124,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product category or return it * } * ``` @@ -2102,63 +2137,63 @@ export interface IProductModuleService { /** * This method is used to retrieve a paginated list of product categories along with the total count of available product categories satisfying the provided filters. - * + * * @param {FilterableProductCategoryProps} filters - The filters to apply on the retrieved product categories. - * @param {FindConfig} config - + * @param {FindConfig} config - * The configurations determining how the product categories are retrieved. Its properties, such as `select` or `relations`, accept the * attributes or relations associated with a product category. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise<[ProductCategoryDTO[], number]>} The list of product categories along with their total count. - * + * * @example * To retrieve a list of product categories using their IDs: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [categories, count] = await productModule.listAndCountCategories({ * id: ids * }) - * + * * // do something with the product category or return it * } * ``` - * + * * To specify relations that should be retrieved within the product categories: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const [categories, count] = await productModule.listAndCountCategories({ * id: ids * }, { * relations: ["parent_category"] * }) - * + * * // do something with the product category or return it * } * ``` - * + * * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[], skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [categories, count] = await productModule.listAndCountCategories({ * id: ids * }, { @@ -2166,21 +2201,21 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product category or return it * } * ``` - * + * * You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: - * + * * ```ts - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function retrieveCategories (ids: string[], name: string, skip: number, take: number) { * const productModule = await initializeProductModule() - * + * * const [categories, count] = await productModule.listAndCountCategories({ * $or: [ * { @@ -2195,7 +2230,7 @@ export interface IProductModuleService { * skip, * take * }) - * + * * // do something with the product category or return it * } * ``` @@ -2208,27 +2243,27 @@ export interface IProductModuleService { /** * This method is used to create a product category. - * + * * @param {CreateProductCategoryDTO} data - The product category to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The created product category. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createCategory (name: string, parent_category_id: string | null) { * const productModule = await initializeProductModule() - * + * * const category = await productModule.createCategory({ * name, * parent_category_id * }) - * + * * // do something with the product category or return it * } - * + * */ createCategory( data: CreateProductCategoryDTO, @@ -2237,24 +2272,24 @@ export interface IProductModuleService { /** * This method is used to update a product category by its ID. - * + * * @param {string} categoryId - The ID of the product category to update. * @param {UpdateProductCategoryDTO} data - The attributes to update in th product category. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The updated product category. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateCategory (id: string, name: string) { * const productModule = await initializeProductModule() - * + * * const category = await productModule.updateCategory(id, { * name, * }) - * + * * // do something with the product category or return it * } */ @@ -2266,19 +2301,19 @@ export interface IProductModuleService { /** * This method is used to delete a product category by its ID. - * + * * @param {string} categoryId - The ID of the product category to delete. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the product category is successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteCategory (id: string) { * const productModule = await initializeProductModule() - * + * * await productModule.deleteCategory(id) * } */ @@ -2286,25 +2321,25 @@ export interface IProductModuleService { /** * This method is used to create a product. - * + * * @param {CreateProductDTO[]} data - The products to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of created products. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function createProduct (title: string) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.create([ * { * title * } * ]) - * + * * // do something with the products or return them * } */ @@ -2315,26 +2350,26 @@ export interface IProductModuleService { /** * This method is used to update a product. - * + * * @param {UpdateProductDTO[]} data - The products to be updated, each holding the attributes that should be updated in the product. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The list of updated products. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function updateProduct (id: string, title: string) { * const productModule = await initializeProductModule() - * + * * const products = await productModule.update([ * { * id, * title * } * ]) - * + * * // do something with the products or return them * } */ @@ -2345,19 +2380,19 @@ export interface IProductModuleService { /** * This method is used to delete products. Unlike the {@link softDelete} method, this method will completely remove the products and they can no longer be accessed or retrieved. - * + * * @param {string[]} productIds - The IDs of the products to be deleted. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} Resolves when the products are successfully deleted. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * await productModule.delete(ids) * } */ @@ -2365,29 +2400,29 @@ export interface IProductModuleService { /** * This method is used to delete products. Unlike the {@link delete} method, this method won't completely remove the product. It can still be accessed or retrieved using methods like {@link retrieve} if you pass the `withDeleted` property to the `config` object parameter. - * + * * The soft-deleted products can be restored using the {@link restore} method. - * + * * @param {string[]} productIds - The IDs of the products to soft-delete. * @param {SoftDeleteReturn} config - * Configurations determining which relations to soft delete along with the each of the products. You can pass to its `returnLinkableKeys` * property any of the product's relation attribute names, such as `variant_id`. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {Promise | void>} + * @returns {Promise | void>} * An object that includes the IDs of related records that were also soft deleted, such as the ID of associated product variants. The object's keys are the ID attribute names of the product entity's relations, such as `variant_id`, and its value is an array of strings, each being the ID of a record associated with the product through this relation, such as the IDs of associated product variants. - * + * * If there are no related records, the promise resolved to `void`. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function deleteProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const cascadedEntities = await productModule.softDelete(ids) - * + * * // do something with the returned cascaded entity IDs or return them * } */ @@ -2399,29 +2434,29 @@ export interface IProductModuleService { /** * This method is used to restore products which were deleted using the {@link softDelete} method. - * + * * @param {string[]} productIds - The IDs of the products to restore. * @param {RestoreReturn} config - * Configurations determining which relations to restore along with the each of the products. You can pass to its `returnLinkableKeys` * property any of the product's relation attribute names, such as `variant_id`. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {Promise | void>} + * @returns {Promise | void>} * An object that includes the IDs of related records that were restored, such as the ID of associated product variants. The object's keys are the ID attribute names of the product entity's relations, such as `variant_id`, and its value is an array of strings, each being the ID of the record associated with the product through this relation, such as the IDs of associated product variants. - * + * * If there are no related records that were restored, the promise resolved to `void`. - * + * * @example - * import { + * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * + * * async function restoreProducts (ids: string[]) { * const productModule = await initializeProductModule() - * + * * const cascadedEntities = await productModule.restore(ids, { * returnLinkableKeys: ["variant_id"] * }) - * + * * // do something with the returned cascaded entity IDs or return them * } */ diff --git a/packages/types/src/workflow/index.ts b/packages/types/src/workflow/index.ts index ecce74d8af45a..57ba877ed972a 100644 --- a/packages/types/src/workflow/index.ts +++ b/packages/types/src/workflow/index.ts @@ -2,3 +2,4 @@ export * as CartWorkflow from "./cart" export * as CommonWorkflow from "./common" export * as ProductWorkflow from "./product" export * as InventoryWorkflow from "./inventory" +export * as PriceListWorkflow from "./price-list" diff --git a/packages/types/src/workflow/price-list/create-price-list.ts b/packages/types/src/workflow/price-list/create-price-list.ts new file mode 100644 index 0000000000000..024a58ddb1c58 --- /dev/null +++ b/packages/types/src/workflow/price-list/create-price-list.ts @@ -0,0 +1,78 @@ +import { + CreatePriceListRules, + PriceListRuleDTO, + PriceListStatus, +} from "../../pricing" + +export interface CreatePriceListDTO { + starts_at?: string + ends_at?: string + status?: PriceListStatus + number_rules?: number + rules?: PriceListRuleDTO[] + prices?: { + amount: number + currency_code: string + region_id?: string + max_quantity?: number + min_quantity?: number + }[] + customer_groups?: { + id: string + }[] +} + +export interface CreatePriceListRuleDTO { + rule_attribute: string + value: string[] +} + +export interface CreatePriceListPriceDTO { + amount: number + currency_code: string + price_set_id: string | null + region_id?: string + max_quantity?: number + min_quantity?: number +} + +export interface CreatePriceListWorkflowInputDTO { + price_lists: CreatePriceListWorkflowDTO[] +} + +export interface RemovePriceListProductsWorkflowInputDTO { + product_ids: string[] + price_list_id: string +} + +export interface RemovePriceListVariantsWorkflowInputDTO { + variant_ids: string[] + price_list_id: string +} + +export interface RemovePriceListPricesWorkflowInputDTO { + money_amount_ids: string[] + price_list_id: string +} + +export interface CreatePriceListWorkflowDTO { + title?: string + name: string + description: string + type?: string + starts_at?: string + ends_at?: string + status?: PriceListStatus + number_rules?: number + prices: InputPrice[] + rules?: CreatePriceListRules +} + +interface InputPrice { + region_id?: string + currency_code: string + amount: number + variant_id: string + min_quantity?: number + max_quantity?: number +} diff --git a/packages/types/src/workflow/price-list/index.ts b/packages/types/src/workflow/price-list/index.ts new file mode 100644 index 0000000000000..3649befbea739 --- /dev/null +++ b/packages/types/src/workflow/price-list/index.ts @@ -0,0 +1,3 @@ +export * from "./create-price-list" +export * from "./update-price-list" +export * from "./remove-price-list" diff --git a/packages/types/src/workflow/price-list/remove-price-list.ts b/packages/types/src/workflow/price-list/remove-price-list.ts new file mode 100644 index 0000000000000..d6789e631e783 --- /dev/null +++ b/packages/types/src/workflow/price-list/remove-price-list.ts @@ -0,0 +1,3 @@ +export interface RemovePriceListWorkflowInputDTO { + price_lists: string[] +} diff --git a/packages/types/src/workflow/price-list/update-price-list.ts b/packages/types/src/workflow/price-list/update-price-list.ts new file mode 100644 index 0000000000000..a0f035267fee6 --- /dev/null +++ b/packages/types/src/workflow/price-list/update-price-list.ts @@ -0,0 +1,25 @@ +import { CreatePriceListRules, PriceListStatus } from "../../pricing" + +import { UpdateProductVariantPricesInputDTO } from "../product" + +export type PriceListVariantPriceDTO = UpdateProductVariantPricesInputDTO & { + variant_id?: string + price_set_id?: string +} + +export interface UpdatePriceListWorkflowDTO { + id: string + name?: string + starts_at?: string + ends_at?: string + status?: PriceListStatus + rules?: CreatePriceListRules + prices?: PriceListVariantPriceDTO[] + customer_groups?: { + id: string + }[] +} + +export interface UpdatePriceListWorkflowInputDTO { + price_lists: UpdatePriceListWorkflowDTO[] +} diff --git a/packages/types/src/workflow/product/create-product-variants.ts b/packages/types/src/workflow/product/create-product-variants.ts new file mode 100644 index 0000000000000..1d7fb0eebad0c --- /dev/null +++ b/packages/types/src/workflow/product/create-product-variants.ts @@ -0,0 +1,32 @@ +import { + UpsertProductVariantOptionInputDTO, + UpsertProductVariantPricesInputDTO, +} from "./update-product-variants" + +export interface CreateProductVariantsInputDTO { + product_id?: string + title?: string + sku?: string + ean?: string + upc?: string + barcode?: string + hs_code?: string + inventory_quantity?: number + allow_backorder?: boolean + manage_inventory?: boolean + weight?: number + length?: number + height?: number + width?: number + origin_country?: string + mid_code?: string + material?: string + metadata?: Record + + prices?: UpsertProductVariantPricesInputDTO[] + options?: UpsertProductVariantOptionInputDTO[] +} + +export interface CreateProductVariantsWorkflowInputDTO { + productVariants: CreateProductVariantsInputDTO[] +} diff --git a/packages/types/src/workflow/product/index.ts b/packages/types/src/workflow/product/index.ts index f960c39643df7..6ff12931de41c 100644 --- a/packages/types/src/workflow/product/index.ts +++ b/packages/types/src/workflow/product/index.ts @@ -1,3 +1,4 @@ +export * from "./create-product-variants" export * from "./create-products" export * from "./update-product-variants" export * from "./update-products" diff --git a/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts b/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts index 11596a9825ed9..0bcc495237a80 100644 --- a/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts +++ b/packages/utils/src/dal/mikro-orm/mikro-orm-repository.ts @@ -137,6 +137,8 @@ export abstract class MikroOrmAbstractBaseRepository retrieveConstraintsToApply: (q: string) => any[] ): void { if (!("q" in findOptions.where) || !findOptions.where.q) { + delete findOptions.where.q + return } diff --git a/packages/workflows/src/definition/index.ts b/packages/workflows/src/definition/index.ts index 50b5440ede1f4..805f14718f34c 100644 --- a/packages/workflows/src/definition/index.ts +++ b/packages/workflows/src/definition/index.ts @@ -1,3 +1,4 @@ export * from "./cart" export * from "./product" export * from "./inventory" +export * from './price-list' \ No newline at end of file diff --git a/packages/workflows/src/definition/price-list/create-price-lists.ts b/packages/workflows/src/definition/price-list/create-price-lists.ts new file mode 100644 index 0000000000000..0a54a3dbb5f25 --- /dev/null +++ b/packages/workflows/src/definition/price-list/create-price-lists.ts @@ -0,0 +1,74 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { PricingTypes, WorkflowTypes } from "@medusajs/types" +import { exportWorkflow, pipe } from "../../helper" + +import { Workflows } from "../../definitions" +import { PriceListHandlers } from "../../handlers" + +export enum CreatePriceListActions { + prepare = "prepare", + createPriceList = "createPriceList", +} + +const workflowSteps: TransactionStepsDefinition = { + next: { + action: CreatePriceListActions.prepare, + noCompensation: true, + next: { + action: CreatePriceListActions.createPriceList, + }, + }, +} + +const handlers = new Map([ + [ + CreatePriceListActions.prepare, + { + invoke: pipe( + { + inputAlias: CreatePriceListActions.prepare, + merge: true, + invoke: { + from: CreatePriceListActions.prepare, + }, + }, + PriceListHandlers.prepareCreatePriceLists + ), + }, + ], + [ + CreatePriceListActions.createPriceList, + { + invoke: pipe( + { + invoke: { + from: CreatePriceListActions.prepare, + alias: PriceListHandlers.createPriceLists.aliases.priceLists, + }, + }, + PriceListHandlers.createPriceLists + ), + compensate: pipe( + { + invoke: { + from: CreatePriceListActions.createPriceList, + alias: PriceListHandlers.removePriceLists.aliases.priceLists, + }, + }, + PriceListHandlers.removePriceLists + ), + }, + ], +]) + +WorkflowManager.register(Workflows.CreatePriceList, workflowSteps, handlers) + +export const createPriceLists = exportWorkflow< + WorkflowTypes.PriceListWorkflow.CreatePriceListWorkflowInputDTO, + { + priceList: PricingTypes.CreatePriceListDTO + }[] +>(Workflows.CreatePriceList, CreatePriceListActions.createPriceList) diff --git a/packages/workflows/src/definition/price-list/index.ts b/packages/workflows/src/definition/price-list/index.ts new file mode 100644 index 0000000000000..28dac74acd6b9 --- /dev/null +++ b/packages/workflows/src/definition/price-list/index.ts @@ -0,0 +1,5 @@ +export * from "./create-price-lists" +export * from "./remove-price-lists" +export * from "./remove-product-prices" +export * from "./remove-variant-prices" +export * from "./update-price-lists" diff --git a/packages/workflows/src/definition/price-list/remove-price-list-prices.ts b/packages/workflows/src/definition/price-list/remove-price-list-prices.ts new file mode 100644 index 0000000000000..086d79cf8ff72 --- /dev/null +++ b/packages/workflows/src/definition/price-list/remove-price-list-prices.ts @@ -0,0 +1,71 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { WorkflowTypes } from "@medusajs/types" +import { exportWorkflow, pipe } from "../../helper" + +import { Workflows } from "../../definitions" +import { PriceListHandlers } from "../../handlers" + +export enum RemovePriceListPricesActions { + prepare = "prepare", + removePriceListPrices = "removePriceListPrices", +} + +const workflowSteps: TransactionStepsDefinition = { + next: { + action: RemovePriceListPricesActions.prepare, + noCompensation: true, + next: { + action: RemovePriceListPricesActions.removePriceListPrices, + noCompensation: true, + }, + }, +} + +const handlers = new Map([ + [ + RemovePriceListPricesActions.prepare, + { + invoke: pipe( + { + inputAlias: RemovePriceListPricesActions.prepare, + merge: true, + invoke: { + from: RemovePriceListPricesActions.prepare, + }, + }, + PriceListHandlers.prepareRemovePriceListPrices + ), + }, + ], + [ + RemovePriceListPricesActions.removePriceListPrices, + { + invoke: pipe( + { + merge: true, + invoke: { + from: RemovePriceListPricesActions.prepare, + }, + }, + PriceListHandlers.removePrices + ), + }, + ], +]) + +WorkflowManager.register( + Workflows.RemovePriceListPrices, + workflowSteps, + handlers +) + +export const removePriceListProductPrices = exportWorkflow< + WorkflowTypes.PriceListWorkflow.RemovePriceListPricesWorkflowInputDTO, + string[] +>( + Workflows.RemovePriceListPrices, + RemovePriceListPricesActions.removePriceListPrices +) diff --git a/packages/workflows/src/definition/price-list/remove-price-lists.ts b/packages/workflows/src/definition/price-list/remove-price-lists.ts new file mode 100644 index 0000000000000..6a4b3f39dc2ae --- /dev/null +++ b/packages/workflows/src/definition/price-list/remove-price-lists.ts @@ -0,0 +1,57 @@ +import { WorkflowTypes } from "@medusajs/types" +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { exportWorkflow, pipe } from "../../helper" + +import { PriceListHandlers } from "../../handlers" +import { Workflows } from "../../definitions" + +export enum RemovePriceListActions { + removePriceList = "removePriceList", +} + +const workflowSteps: TransactionStepsDefinition = { + next: { + action: RemovePriceListActions.removePriceList, + noCompensation: true, + }, +} + +const handlers = new Map([ + [ + RemovePriceListActions.removePriceList, + { + invoke: pipe( + { + inputAlias: RemovePriceListActions.removePriceList, + merge: true, + invoke: { + from: RemovePriceListActions.removePriceList, + }, + }, + PriceListHandlers.removePriceLists + ), + }, + ], +]) + +WorkflowManager.register(Workflows.DeletePriceLists, workflowSteps, handlers) + +export const removePriceLists = exportWorkflow< + WorkflowTypes.PriceListWorkflow.RemovePriceListWorkflowInputDTO, + { + price_list_ids: string[] + } +>( + Workflows.DeletePriceLists, + RemovePriceListActions.removePriceList, + async (data) => { + return { + price_lists: data.price_lists.map((priceListId) => ({ + price_list: { id: priceListId }, + })), + } + } +) diff --git a/packages/workflows/src/definition/price-list/remove-product-prices.ts b/packages/workflows/src/definition/price-list/remove-product-prices.ts new file mode 100644 index 0000000000000..248129c00d842 --- /dev/null +++ b/packages/workflows/src/definition/price-list/remove-product-prices.ts @@ -0,0 +1,72 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { WorkflowTypes } from "@medusajs/types" +import { exportWorkflow, pipe } from "../../helper" + +import { Workflows } from "../../definitions" +import { PriceListHandlers } from "../../handlers" + +export enum RemoveProductPricesActions { + prepare = "prepare", + removePriceListPriceSetPrices = "removePriceListPriceSetPrices", +} + +const workflowSteps: TransactionStepsDefinition = { + next: { + action: RemoveProductPricesActions.prepare, + noCompensation: true, + next: { + action: RemoveProductPricesActions.removePriceListPriceSetPrices, + noCompensation: true, + }, + }, +} + +const handlers = new Map([ + [ + RemoveProductPricesActions.prepare, + { + invoke: pipe( + { + inputAlias: RemoveProductPricesActions.prepare, + merge: true, + invoke: { + from: RemoveProductPricesActions.prepare, + }, + }, + PriceListHandlers.prepareRemoveProductPrices + ), + }, + ], + [ + RemoveProductPricesActions.removePriceListPriceSetPrices, + { + invoke: pipe( + { + merge: true, + invoke: { + from: RemoveProductPricesActions.prepare, + alias: PriceListHandlers.createPriceLists.aliases.priceLists, + }, + }, + PriceListHandlers.removePriceListPriceSetPrices + ), + }, + ], +]) + +WorkflowManager.register( + Workflows.RemovePriceListProductPrices, + workflowSteps, + handlers +) + +export const removePriceListProductPrices = exportWorkflow< + WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO, + string[] +>( + Workflows.RemovePriceListProductPrices, + RemoveProductPricesActions.removePriceListPriceSetPrices +) diff --git a/packages/workflows/src/definition/price-list/remove-variant-prices.ts b/packages/workflows/src/definition/price-list/remove-variant-prices.ts new file mode 100644 index 0000000000000..b68ef60ed75c1 --- /dev/null +++ b/packages/workflows/src/definition/price-list/remove-variant-prices.ts @@ -0,0 +1,72 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { WorkflowTypes } from "@medusajs/types" +import { exportWorkflow, pipe } from "../../helper" + +import { Workflows } from "../../definitions" +import { PriceListHandlers } from "../../handlers" + +export enum RemoveVariantPricesActions { + prepare = "prepare", + removePriceListPriceSetPrices = "removePriceListPriceSetPrices", +} + +const workflowSteps: TransactionStepsDefinition = { + next: { + action: RemoveVariantPricesActions.prepare, + noCompensation: true, + next: { + action: RemoveVariantPricesActions.removePriceListPriceSetPrices, + noCompensation: true, + }, + }, +} + +const handlers = new Map([ + [ + RemoveVariantPricesActions.prepare, + { + invoke: pipe( + { + inputAlias: RemoveVariantPricesActions.prepare, + merge: true, + invoke: { + from: RemoveVariantPricesActions.prepare, + }, + }, + PriceListHandlers.prepareRemoveVariantPrices + ), + }, + ], + [ + RemoveVariantPricesActions.removePriceListPriceSetPrices, + { + invoke: pipe( + { + merge: true, + invoke: { + from: RemoveVariantPricesActions.prepare, + alias: PriceListHandlers.createPriceLists.aliases.priceLists, + }, + }, + PriceListHandlers.removePriceListPriceSetPrices + ), + }, + ], +]) + +WorkflowManager.register( + Workflows.RemovePriceListVariantPrices, + workflowSteps, + handlers +) + +export const removePriceListVariantPrices = exportWorkflow< + WorkflowTypes.PriceListWorkflow.RemovePriceListVariantsWorkflowInputDTO, + string[] +>( + Workflows.RemovePriceListVariantPrices, + RemoveVariantPricesActions.removePriceListPriceSetPrices +) diff --git a/packages/workflows/src/definition/price-list/update-price-lists.ts b/packages/workflows/src/definition/price-list/update-price-lists.ts new file mode 100644 index 0000000000000..a445714199b55 --- /dev/null +++ b/packages/workflows/src/definition/price-list/update-price-lists.ts @@ -0,0 +1,65 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { WorkflowTypes } from "@medusajs/types" +import { exportWorkflow, pipe } from "../../helper" + +import { Workflows } from "../../definitions" +import { PriceListHandlers } from "../../handlers" + +export enum UpdatePriceListActions { + prepare = "prepare", + updatePriceList = "updatePriceList", +} + +const workflowSteps: TransactionStepsDefinition = { + action: UpdatePriceListActions.prepare, + noCompensation: true, + next: { + next: { + noCompensation: true, + action: UpdatePriceListActions.updatePriceList, + }, + }, +} + +const handlers = new Map([ + [ + UpdatePriceListActions.prepare, + { + invoke: pipe( + { + inputAlias: UpdatePriceListActions.prepare, + merge: true, + invoke: { + from: UpdatePriceListActions.prepare, + }, + }, + PriceListHandlers.prepareUpdatePriceLists + ), + }, + ], + [ + UpdatePriceListActions.updatePriceList, + { + invoke: pipe( + { + inputAlias: UpdatePriceListActions.updatePriceList, + merge: true, + invoke: { + from: UpdatePriceListActions.prepare, + }, + }, + PriceListHandlers.updatePriceLists + ), + }, + ], +]) + +WorkflowManager.register(Workflows.UpdatePriceLists, workflowSteps, handlers) + +export const updatePriceLists = exportWorkflow< + WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowInputDTO, + { priceList: WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowDTO }[] +>(Workflows.UpdatePriceLists, UpdatePriceListActions.updatePriceList) diff --git a/packages/workflows/src/definition/product/create-product-variants.ts b/packages/workflows/src/definition/product/create-product-variants.ts new file mode 100644 index 0000000000000..0322af48a2ccc --- /dev/null +++ b/packages/workflows/src/definition/product/create-product-variants.ts @@ -0,0 +1,121 @@ +import { + TransactionStepsDefinition, + WorkflowManager, +} from "@medusajs/orchestration" +import { InputAlias, Workflows } from "../../definitions" +import { exportWorkflow, pipe } from "../../helper" + +import { ProductTypes, WorkflowTypes } from "@medusajs/types" +import { ProductHandlers } from "../../handlers" + +export enum CreateProductVariantsActions { + prepare = "prepare", + createProductVariants = "createProductVariants", + revertProductVariantsCreate = "revertProductVariantsCreate", + upsertPrices = "upsertPrices", +} + +export const workflowSteps: TransactionStepsDefinition = { + next: { + action: CreateProductVariantsActions.prepare, + noCompensation: true, + next: { + action: CreateProductVariantsActions.createProductVariants, + next: [ + { + action: CreateProductVariantsActions.upsertPrices, + }, + ], + }, + }, +} + +const handlers = new Map([ + [ + CreateProductVariantsActions.prepare, + { + invoke: pipe( + { + merge: true, + inputAlias: InputAlias.ProductVariantsCreateInputData, + invoke: { + from: InputAlias.ProductVariantsCreateInputData, + }, + }, + ProductHandlers.createProductVariantsPrepareData + ), + }, + ], + [ + CreateProductVariantsActions.createProductVariants, + { + invoke: pipe( + { + merge: true, + invoke: { + from: CreateProductVariantsActions.prepare, + }, + }, + ProductHandlers.createProductVariants + ), + compensate: pipe( + { + merge: true, + invoke: [ + { + from: CreateProductVariantsActions.prepare, + }, + { + from: CreateProductVariantsActions.createProductVariants, + }, + ], + }, + ProductHandlers.removeProductVariants + ), + }, + ], + [ + CreateProductVariantsActions.upsertPrices, + { + invoke: pipe( + { + merge: true, + invoke: [ + { + from: CreateProductVariantsActions.createProductVariants, + }, + ], + }, + ProductHandlers.upsertVariantPrices + ), + compensate: pipe( + { + merge: true, + invoke: [ + { + from: CreateProductVariantsActions.prepare, + }, + { + from: CreateProductVariantsActions.upsertPrices, + }, + ], + }, + ProductHandlers.revertVariantPrices + ), + }, + ], +]) + +WorkflowManager.register( + Workflows.CreateProductVariants, + workflowSteps, + handlers +) + +export const createProductVariants = exportWorkflow< + WorkflowTypes.ProductWorkflow.CreateProductVariantsWorkflowInputDTO, + ProductTypes.ProductVariantDTO[] +>( + Workflows.CreateProductVariants, + CreateProductVariantsActions.createProductVariants +) diff --git a/packages/workflows/src/definition/product/index.ts b/packages/workflows/src/definition/product/index.ts index ab2a40334d17b..c138e52cdd69f 100644 --- a/packages/workflows/src/definition/product/index.ts +++ b/packages/workflows/src/definition/product/index.ts @@ -1,3 +1,4 @@ +export * as CreateProductVariants from "./create-product-variants" export * from "./create-products" export * as UpdateProductVariants from "./update-product-variants" export * from "./update-products" diff --git a/packages/workflows/src/definitions.ts b/packages/workflows/src/definitions.ts index 5f4fa84616e20..645b88ce4e4a2 100644 --- a/packages/workflows/src/definitions.ts +++ b/packages/workflows/src/definitions.ts @@ -4,12 +4,21 @@ export enum Workflows { UpdateProducts = "update-products", // Product Variant workflows + CreateProductVariants = "create-product-variants", UpdateProductVariants = "update-product-variants", // Cart workflows CreateCart = "create-cart", CreateInventoryItems = "create-inventory-items", + + // Price list workflows + CreatePriceList = "create-price-list", + UpdatePriceLists = "update-price-lists", + DeletePriceLists = "delete-price-lists", + RemovePriceListProductPrices = "remove-price-list-products", + RemovePriceListVariantPrices = "remove-price-list-variants", + RemovePriceListPrices = "remove-price-list-prices", } export enum InputAlias { @@ -19,6 +28,7 @@ export enum InputAlias { ProductVariants = "productVariants", ProductVariantsUpdateInputData = "productVariantsUpdateInputData", + ProductVariantsCreateInputData = "productVariantsCreateInputData", InventoryItems = "inventoryItems", RemovedInventoryItems = "removedInventoryItems", diff --git a/packages/workflows/src/handlers/index.ts b/packages/workflows/src/handlers/index.ts index 5c0282342f7d9..2c3607b6670be 100644 --- a/packages/workflows/src/handlers/index.ts +++ b/packages/workflows/src/handlers/index.ts @@ -4,6 +4,7 @@ export * as CommonHandlers from "./common" export * as CustomerHandlers from "./customer" export * as InventoryHandlers from "./inventory" export * as MiddlewaresHandlers from "./middlewares" +export * as PriceListHandlers from "./price-list" export * as ProductHandlers from "./product" export * as RegionHandlers from "./region" export * as SalesChannelHandlers from "./sales-channel" diff --git a/packages/workflows/src/handlers/price-list/create-price-list.ts b/packages/workflows/src/handlers/price-list/create-price-list.ts new file mode 100644 index 0000000000000..1e69066082853 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/create-price-list.ts @@ -0,0 +1,42 @@ +import { + CreatePriceListDTO, + IPricingModuleService, + PriceListDTO, +} from "@medusajs/types" + +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { WorkflowArguments } from "../../helper" + +type Result = { + priceList: PriceListDTO +}[] + +type Input = { + tag?: string + priceList: CreatePriceListDTO +}[] + +export async function createPriceLists({ + container, + data, +}: WorkflowArguments<{ + priceLists: Input +}>): Promise { + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + return await Promise.all( + data.priceLists.map(async (item) => { + const [priceList] = await pricingService!.createPriceLists([ + item.priceList, + ]) + + return { tag: item.tag ?? priceList.id, priceList } + }) + ) +} + +createPriceLists.aliases = { + priceLists: "priceLists", +} diff --git a/packages/workflows/src/handlers/price-list/index.ts b/packages/workflows/src/handlers/price-list/index.ts new file mode 100644 index 0000000000000..9f95fd8c6b026 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/index.ts @@ -0,0 +1,10 @@ +export * from "./create-price-list" +export * from "./prepare-create-price-list" +export * from "./prepare-update-price-lists" +export * from "./remove-price-list" +export * from "./update-price-lists" +export * from "./prepare-remove-product-prices" +export * from "./remove-price-set-price-list-prices" +export * from "./prepare-remove-variant-prices" +export * from "./prepare-remove-price-list-prices" +export * from "./remove-prices" diff --git a/packages/workflows/src/handlers/price-list/prepare-create-price-list.ts b/packages/workflows/src/handlers/price-list/prepare-create-price-list.ts new file mode 100644 index 0000000000000..327badb612edd --- /dev/null +++ b/packages/workflows/src/handlers/price-list/prepare-create-price-list.ts @@ -0,0 +1,87 @@ +import { CreatePriceListDTO, PriceListWorkflow } from "@medusajs/types" +import { MedusaError } from "@medusajs/utils" +import { WorkflowArguments } from "../../helper" + +type Result = { + tag?: string + priceList: CreatePriceListDTO +}[] + +export async function prepareCreatePriceLists({ + container, + data, +}: WorkflowArguments<{ + price_lists: (PriceListWorkflow.CreatePriceListWorkflowDTO & { + _associationTag?: string + })[] +}>): Promise { + const remoteQuery = container.resolve("remoteQuery") + + const { price_lists } = data + + const variantIds = price_lists + .map((priceList) => priceList.prices.map((price) => price.variant_id)) + .flat() + + const variables = { + variant_id: variantIds, + } + + const query = { + product_variant_price_set: { + __args: variables, + fields: ["variant_id", "price_set_id"], + }, + } + + const variantPriceSets = await remoteQuery(query) + + const variantIdPriceSetIdMap: Map = new Map( + variantPriceSets.map((variantPriceSet) => [ + variantPriceSet.variant_id, + variantPriceSet.price_set_id, + ]) + ) + + const variantsWithoutPriceSets: string[] = [] + + for (const variantId of variantIds) { + if (!variantIdPriceSetIdMap.has(variantId)) { + variantsWithoutPriceSets.push(variantId) + } + } + + if (variantsWithoutPriceSets.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `No priceSet exist for variants: ${variantsWithoutPriceSets.join(", ")}` + ) + } + + return price_lists.map((priceListDTO) => { + priceListDTO.title ??= priceListDTO.name + const { _associationTag, name, prices, ...rest } = priceListDTO + + const priceList = rest as CreatePriceListDTO + + priceList.rules ??= {} + priceList.prices = + prices?.map((price) => { + const price_set_id = variantIdPriceSetIdMap.get(price.variant_id)! + + return { + currency_code: price.currency_code, + amount: price.amount, + min_quantity: price.min_quantity, + max_quantity: price.max_quantity, + price_set_id, + } + }) ?? [] + + return { priceList, tag: _associationTag } + }) +} + +prepareCreatePriceLists.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/price-list/prepare-remove-price-list-prices.ts b/packages/workflows/src/handlers/price-list/prepare-remove-price-list-prices.ts new file mode 100644 index 0000000000000..e31a63cb185c5 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/prepare-remove-price-list-prices.ts @@ -0,0 +1,48 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { IPricingModuleService } from "@medusajs/types" +import { WorkflowArguments } from "../../helper" + +type Result = { + moneyAmountIds: string[] + priceListId: string +} + +export async function prepareRemovePriceListPrices({ + container, + data, +}: WorkflowArguments<{ + money_amount_ids: string[] + price_list_id: string +}>): Promise { + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + const { + price_list_id: priceListId, + money_amount_ids: moneyAmountIdsToDelete, + } = data + + const moneyAmounts = await pricingService.listMoneyAmounts( + { id: moneyAmountIdsToDelete }, + { + relations: [ + "price_set_money_amount", + "price_set_money_amount.price_list", + ], + } + ) + + const moneyAmountIds = moneyAmounts + .filter( + (moneyAmount) => + moneyAmount?.price_set_money_amount?.price_list?.id === priceListId + ) + .map((ma) => ma.id) + + return { moneyAmountIds, priceListId } +} + +prepareRemovePriceListPrices.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/price-list/prepare-remove-product-prices.ts b/packages/workflows/src/handlers/price-list/prepare-remove-product-prices.ts new file mode 100644 index 0000000000000..34b22b9000f32 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/prepare-remove-product-prices.ts @@ -0,0 +1,62 @@ +import { WorkflowArguments } from "../../helper" +import { prepareCreatePriceLists } from "./prepare-create-price-list" + +type Result = { + priceSetIds: string[] + priceListId: string +} + +export async function prepareRemoveProductPrices({ + container, + data, +}: WorkflowArguments<{ + product_ids: string[] + price_list_id: string +}>): Promise { + const remoteQuery = container.resolve("remoteQuery") + + const { price_list_id, product_ids } = data + + const variables = { + id: product_ids, + } + + const query = { + product: { + __args: variables, + ...defaultAdminProductRemoteQueryObject, + }, + } + + const productsWithVariantPriceSets: QueryResult[] = await remoteQuery(query) + + const priceSetIds = productsWithVariantPriceSets + .map(({ variants }) => variants.map(({ price }) => price.price_set_id)) + .flat() + + return { priceSetIds, priceListId: price_list_id } +} + +prepareCreatePriceLists.aliases = { + payload: "payload", +} + +type QueryResult = { + id: string + variants: { + id: string + price: { + price_set_id: string + variant_id: string + } + }[] +} + +const defaultAdminProductRemoteQueryObject = { + fields: ["id"], + variants: { + price: { + fields: ["variant_id", "price_set_id"], + }, + }, +} diff --git a/packages/workflows/src/handlers/price-list/prepare-remove-variant-prices.ts b/packages/workflows/src/handlers/price-list/prepare-remove-variant-prices.ts new file mode 100644 index 0000000000000..d903fd459ffeb --- /dev/null +++ b/packages/workflows/src/handlers/price-list/prepare-remove-variant-prices.ts @@ -0,0 +1,56 @@ +import { WorkflowArguments } from "../../helper" +import { prepareCreatePriceLists } from "./prepare-create-price-list" + +type Result = { + priceSetIds: string[] + priceListId: string +} + +export async function prepareRemoveVariantPrices({ + container, + data, +}: WorkflowArguments<{ + variant_ids: string[] + price_list_id: string +}>): Promise { + const remoteQuery = container.resolve("remoteQuery") + + const { price_list_id, variant_ids } = data + + const variables = { + variant_id: variant_ids, + } + + const query = { + product_variant_price_set: { + __args: variables, + fields: ["variant_id", "price_set_id"], + }, + } + + const productsWithVariantPriceSets: QueryResult[] = await remoteQuery(query) + + const priceSetIds = productsWithVariantPriceSets.map( + (variantPriceSet) => variantPriceSet.price_set_id + ) + + return { priceSetIds, priceListId: price_list_id } +} + +prepareCreatePriceLists.aliases = { + payload: "payload", +} + +type QueryResult = { + price_set_id: string + variant_id: string +} + +const defaultAdminProductRemoteQueryObject = { + fields: ["id"], + variants: { + price: { + fields: ["variant_id", "price_set_id"], + }, + }, +} diff --git a/packages/workflows/src/handlers/price-list/prepare-update-price-lists.ts b/packages/workflows/src/handlers/price-list/prepare-update-price-lists.ts new file mode 100644 index 0000000000000..490974b395560 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/prepare-update-price-lists.ts @@ -0,0 +1,87 @@ +import { + PriceListPriceDTO, + UpdatePriceListDTO, + WorkflowTypes, +} from "@medusajs/types" +import { WorkflowArguments } from "../../helper" + +type Result = { + priceLists: UpdatePriceListDTO[] + priceListPricesMap: Map +} + +export async function prepareUpdatePriceLists({ + container, + data, +}: WorkflowArguments<{ + price_lists: WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowDTO[] +}>): Promise { + const { price_lists: priceListsData } = data + const remoteQuery = container.resolve("remoteQuery") + + const variantPriceSetMap = new Map() + const priceListPricesMap = new Map() + + const variantIds = priceListsData + .map((priceListData) => priceListData.prices?.map((p) => p.variant_id)) + .flat() + + const variables = { + variant_id: variantIds, + } + + const query = { + product_variant_price_set: { + __args: variables, + fields: ["variant_id", "price_set_id"], + }, + } + + const variantPriceSets = await remoteQuery(query) + + for (const { variant_id, price_set_id } of variantPriceSets) { + variantPriceSetMap.set(variant_id, price_set_id) + } + + const priceLists = priceListsData.map((priceListData) => { + const priceListPrices: PriceListPriceDTO[] = [] + + priceListData.prices?.forEach((price) => { + const { variant_id, ...priceData } = price + if (!variant_id) { + return + } + + priceListPrices.push({ + id: priceData.id, + price_set_id: variantPriceSetMap.get(variant_id) as string, + currency_code: priceData.currency_code as string, + amount: priceData.amount, + min_quantity: priceData.min_quantity, + max_quantity: priceData.max_quantity, + }) + + return + }) + + priceListPricesMap.set(priceListData.id, priceListPrices) + + delete priceListData?.prices + + const priceListDataClone: UpdatePriceListDTO = { + ...priceListData, + } + + if (priceListData.name) { + priceListDataClone.title = priceListData.name + } + + return priceListDataClone + }) + + return { priceLists, priceListPricesMap } +} + +prepareUpdatePriceLists.aliases = { + payload: "prepare", +} diff --git a/packages/workflows/src/handlers/price-list/remove-price-list.ts b/packages/workflows/src/handlers/price-list/remove-price-list.ts new file mode 100644 index 0000000000000..b38bd92ccaeb9 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/remove-price-list.ts @@ -0,0 +1,31 @@ +import { IPricingModuleService, PriceListDTO } from "@medusajs/types" + +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { WorkflowArguments } from "../../helper" + +export async function removePriceLists({ + container, + data, +}: WorkflowArguments<{ + price_lists: { + price_list: PriceListDTO + }[] +}>): Promise< + { + price_list: PriceListDTO + }[] +> { + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + await pricingService!.deletePriceLists( + data.price_lists.map(({ price_list }) => price_list.id) + ) + + return data.price_lists +} + +removePriceLists.aliases = { + priceLists: "priceLists", +} diff --git a/packages/workflows/src/handlers/price-list/remove-price-set-price-list-prices.ts b/packages/workflows/src/handlers/price-list/remove-price-set-price-list-prices.ts new file mode 100644 index 0000000000000..09ce0a382d1c2 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/remove-price-set-price-list-prices.ts @@ -0,0 +1,39 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { IPricingModuleService } from "@medusajs/types" +import { WorkflowArguments } from "../../helper" +import { prepareCreatePriceLists } from "./prepare-create-price-list" + +export async function removePriceListPriceSetPrices({ + container, + data, +}: WorkflowArguments<{ + priceSetIds: string[] + priceListId: string +}>): Promise { + const { priceSetIds, priceListId } = data + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + const priceSetMoneyAmounts = await pricingService.listPriceSetMoneyAmounts( + { + price_set_id: priceSetIds, + price_list_id: [priceListId], + }, + { + relations: ["money_amount"], + } + ) + + const moneyAmountIDs = priceSetMoneyAmounts + .map((priceSetMoneyAmount) => priceSetMoneyAmount.money_amount?.id) + .filter((moneyAmountId): moneyAmountId is string => !!moneyAmountId) + + await pricingService.deleteMoneyAmounts(moneyAmountIDs) + + return moneyAmountIDs +} + +prepareCreatePriceLists.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/price-list/remove-prices.ts b/packages/workflows/src/handlers/price-list/remove-prices.ts new file mode 100644 index 0000000000000..159f74050ef36 --- /dev/null +++ b/packages/workflows/src/handlers/price-list/remove-prices.ts @@ -0,0 +1,29 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { IPricingModuleService } from "@medusajs/types" +import { WorkflowArguments } from "../../helper" + +type Result = { + deletedPriceIds: string[] +} + +export async function removePrices({ + container, + data, +}: WorkflowArguments<{ + moneyAmountIds: string[] +}>): Promise { + const { moneyAmountIds } = data + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + await pricingService.deleteMoneyAmounts(moneyAmountIds) + + return { + deletedPriceIds: moneyAmountIds, + } +} + +removePrices.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/price-list/update-price-lists.ts b/packages/workflows/src/handlers/price-list/update-price-lists.ts new file mode 100644 index 0000000000000..4e62603e47f3e --- /dev/null +++ b/packages/workflows/src/handlers/price-list/update-price-lists.ts @@ -0,0 +1,63 @@ +import { + AddPriceListPricesDTO, + IPricingModuleService, + PriceListDTO, + PriceListPriceDTO, + UpdateMoneyAmountDTO, + UpdatePriceListDTO, +} from "@medusajs/types" + +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { WorkflowArguments } from "../../helper" + +type Result = { + priceLists: PriceListDTO[] +} + +export async function updatePriceLists({ + container, + data, +}: WorkflowArguments<{ + priceLists: UpdatePriceListDTO[] + priceListPricesMap: Map +}>): Promise { + const { priceLists: priceListsData, priceListPricesMap } = data + const pricingService: IPricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) + + const priceLists = await pricingService.updatePriceLists(priceListsData) + const addPriceListPricesData: AddPriceListPricesDTO[] = [] + const moneyAmountsToUpdate: UpdateMoneyAmountDTO[] = [] + + for (const [priceListId, prices] of priceListPricesMap.entries()) { + const moneyAmountsToCreate: PriceListPriceDTO[] = [] + + for (const price of prices) { + if (price.id) { + moneyAmountsToUpdate.push(price as UpdateMoneyAmountDTO) + } else { + moneyAmountsToCreate.push(price) + } + } + + addPriceListPricesData.push({ + priceListId, + prices: moneyAmountsToCreate, + }) + } + + if (addPriceListPricesData.length) { + await pricingService.addPriceListPrices(addPriceListPricesData) + } + + if (moneyAmountsToUpdate.length) { + await pricingService.updateMoneyAmounts(moneyAmountsToUpdate) + } + + return { priceLists } +} + +updatePriceLists.aliases = { + payload: "updatePriceLists", +} diff --git a/packages/workflows/src/handlers/product/create-product-variants-prepare-data.ts b/packages/workflows/src/handlers/product/create-product-variants-prepare-data.ts new file mode 100644 index 0000000000000..daadc4d82734d --- /dev/null +++ b/packages/workflows/src/handlers/product/create-product-variants-prepare-data.ts @@ -0,0 +1,67 @@ +import { ProductWorkflow, WorkflowTypes } from "@medusajs/types" + +import { WorkflowArguments } from "../../helper" + +type VariantPrice = { + region_id?: string + currency_code?: string + amount: number + min_quantity?: number + max_quantity?: number +} + +export type CreateProductVariantsPreparedData = { + productVariants: ProductWorkflow.CreateProductVariantsInputDTO[] + variantIndexPricesMap: Map + productVariantsMap: Map< + string, + ProductWorkflow.CreateProductVariantsInputDTO[] + > +} + +export async function createProductVariantsPrepareData({ + container, + data, +}: WorkflowArguments): Promise { + const featureFlagRouter = container.resolve("featureFlagRouter") + const productVariants: ProductWorkflow.CreateProductVariantsInputDTO[] = + data.productVariants || [] + + const variantIndexPricesMap = new Map() + const productVariantsMap = new Map< + string, + ProductWorkflow.CreateProductVariantsInputDTO[] + >() + + for (const [index, productVariantData] of productVariants.entries()) { + if (!productVariantData.product_id) { + continue + } + + variantIndexPricesMap.set(index, productVariantData.prices || []) + + delete productVariantData.prices + + const productVariants = productVariantsMap.get( + productVariantData.product_id + ) + + if (productVariants) { + productVariants.push(productVariantData) + } else { + productVariantsMap.set(productVariantData.product_id, [ + productVariantData, + ]) + } + } + + return { + productVariants, + variantIndexPricesMap, + productVariantsMap, + } +} + +createProductVariantsPrepareData.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/product/create-product-variants.ts b/packages/workflows/src/handlers/product/create-product-variants.ts new file mode 100644 index 0000000000000..054877d5a59ce --- /dev/null +++ b/packages/workflows/src/handlers/product/create-product-variants.ts @@ -0,0 +1,46 @@ +import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" +import { ProductTypes } from "@medusajs/types" +import { WorkflowArguments } from "../../helper" + +type VariantPrice = { + region_id?: string + currency_code?: string + amount: number + min_quantity?: number + max_quantity?: number +} + +type HandlerInput = { + productVariantsMap: Map + variantIndexPricesMap: Map +} + +export async function createProductVariants({ + container, + data, +}: WorkflowArguments): Promise<{ + productVariants: ProductTypes.ProductVariantDTO[] + variantPricesMap: Map +}> { + const { productVariantsMap, variantIndexPricesMap } = data + const variantPricesMap = new Map() + const productModuleService: ProductTypes.IProductModuleService = + container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName) + + const productVariants = await productModuleService.createVariants( + [...productVariantsMap.values()].flat() + ) + + productVariants.forEach((variant, index) => { + variantPricesMap.set(variant.id, variantIndexPricesMap.get(index) || []) + }) + + return { + productVariants, + variantPricesMap, + } +} + +createProductVariants.aliases = { + payload: "payload", +} diff --git a/packages/workflows/src/handlers/product/create-products-prepare-data.ts b/packages/workflows/src/handlers/product/create-products-prepare-data.ts index b6b2f1c0c6c18..ebce044b592d3 100644 --- a/packages/workflows/src/handlers/product/create-products-prepare-data.ts +++ b/packages/workflows/src/handlers/product/create-products-prepare-data.ts @@ -1,8 +1,8 @@ import { ProductTypes, SalesChannelTypes, WorkflowTypes } from "@medusajs/types" import { FeatureFlagUtils, - ShippingProfileUtils, kebabCase, + ShippingProfileUtils, } from "@medusajs/utils" import { WorkflowArguments } from "../../helper" @@ -114,23 +114,17 @@ export async function createProductsPrepareData({ } if (product.variants) { - const hasPrices = product.variants.some((variant) => { - return (variant.prices?.length ?? 0) > 0 - }) + const items = + productsHandleVariantsIndexPricesMap.get(product.handle!) ?? [] - if (hasPrices) { - const items = - productsHandleVariantsIndexPricesMap.get(product.handle!) ?? [] - - product.variants.forEach((variant, index) => { - items.push({ - index, - prices: variant.prices!, - }) + product.variants.forEach((variant, index) => { + items.push({ + index, + prices: variant.prices!, }) + }) - productsHandleVariantsIndexPricesMap.set(product.handle!, items) - } + productsHandleVariantsIndexPricesMap.set(product.handle!, items) } } diff --git a/packages/workflows/src/handlers/product/index.ts b/packages/workflows/src/handlers/product/index.ts index 697c0e0b83ac7..bfadce740dfa4 100644 --- a/packages/workflows/src/handlers/product/index.ts +++ b/packages/workflows/src/handlers/product/index.ts @@ -1,10 +1,13 @@ export * from "./attach-sales-channel-to-products" export * from "./attach-shipping-profile-to-products" +export * from "./create-product-variants" +export * from "./create-product-variants-prepare-data" export * from "./create-products" export * from "./create-products-prepare-data" export * from "./detach-sales-channel-from-products" export * from "./detach-shipping-profile-from-products" export * from "./list-products" +export * from "./remove-product-variants" export * from "./remove-products" export * from "./revert-update-products" export * from "./revert-variant-prices" diff --git a/packages/workflows/src/handlers/product/remove-product-variants.ts b/packages/workflows/src/handlers/product/remove-product-variants.ts new file mode 100644 index 0000000000000..d40edf7a4b732 --- /dev/null +++ b/packages/workflows/src/handlers/product/remove-product-variants.ts @@ -0,0 +1,26 @@ +import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" +import { IProductModuleService } from "@medusajs/types" +import { WorkflowArguments } from "../../helper" + +type HandlerInput = { productVariants: { id: string }[] } + +export async function removeProductVariants({ + container, + data, +}: WorkflowArguments): Promise { + if (!data.productVariants.length) { + return + } + + const productModuleService: IProductModuleService = container.resolve( + ModulesDefinition[Modules.PRODUCT].registrationName + ) + + await productModuleService.deleteVariants( + data.productVariants.map((p) => p.id) + ) +} + +removeProductVariants.aliases = { + productVariants: "productVariants", +} diff --git a/packages/workflows/src/handlers/product/update-product-variants.ts b/packages/workflows/src/handlers/product/update-product-variants.ts index 3f057c91f1b78..e91c6775a45ab 100644 --- a/packages/workflows/src/handlers/product/update-product-variants.ts +++ b/packages/workflows/src/handlers/product/update-product-variants.ts @@ -1,5 +1,5 @@ import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" -import { ProductTypes } from "@medusajs/types" +import { ProductTypes, UpdateProductVariantOnlyDTO } from "@medusajs/types" import { WorkflowArguments } from "../../helper" type HandlerInput = { @@ -14,21 +14,22 @@ export async function updateProductVariants({ > { const { productVariantsMap } = data const productsVariants: ProductTypes.UpdateProductVariantDTO[] = [] - const updateProductsData: ProductTypes.UpdateProductDTO[] = [] + const updateVariantsData: ProductTypes.UpdateProductVariantOnlyDTO[] = [] const productModuleService: ProductTypes.IProductModuleService = container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName) - for (const [productId, variantsData = []] of productVariantsMap) { - updateProductsData.push({ - id: productId, - variants: variantsData, - }) + for (const [product_id, variantsUpdateData = []] of productVariantsMap) { + updateVariantsData.push( + ...(variantsUpdateData as unknown as UpdateProductVariantOnlyDTO[]).map( + (update) => ({ ...update, product_id }) + ) + ) - productsVariants.push(...variantsData) + productsVariants.push(...variantsUpdateData) } - if (updateProductsData.length) { - await productModuleService.update(updateProductsData) + if (updateVariantsData.length) { + await productModuleService.updateVariants(updateVariantsData) } return productsVariants diff --git a/packages/workflows/src/handlers/product/upsert-variant-prices.ts b/packages/workflows/src/handlers/product/upsert-variant-prices.ts index abe7de74d502d..441ed9d3e1509 100644 --- a/packages/workflows/src/handlers/product/upsert-variant-prices.ts +++ b/packages/workflows/src/handlers/product/upsert-variant-prices.ts @@ -23,11 +23,9 @@ type HandlerInput = { export async function upsertVariantPrices({ container, - context, data, }: WorkflowArguments) { const { variantPricesMap } = data - const featureFlagRouter = container.resolve("featureFlagRouter") if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { @@ -80,29 +78,34 @@ export async function upsertVariantPrices({ ) for (const price of prices) { + const region = price.region_id && regionsMap.get(price.region_id) + let region_currency_code: string | undefined + let region_rules: Record | undefined + + if (region) { + region_currency_code = region.currency_code + region_rules = { + region_id: region.id, + } + } + if (price.id) { - moneyAmountsToUpdate.push({ + const priceToUpdate = { id: price.id, min_quantity: price.min_quantity, max_quantity: price.max_quantity, amount: price.amount, - currency_code: price.currency_code, - }) + currency_code: region_currency_code ?? price.currency_code, + } + + moneyAmountsToUpdate.push(priceToUpdate) } else { - const region = price.region_id && regionsMap.get(price.region_id) const variantPrice: PricingTypes.CreatePricesDTO = { min_quantity: price.min_quantity, max_quantity: price.max_quantity, amount: price.amount, - currency_code: price.currency_code, - rules: {}, - } - - if (region) { - variantPrice.currency_code = region.currency_code - variantPrice.rules = { - region_id: region.id, - } + currency_code: region_currency_code ?? price.currency_code, + rules: region_rules ?? {}, } delete price.region_id @@ -129,16 +132,16 @@ export async function upsertVariantPrices({ priceSetId = createdPriceSet?.id createdPriceSets.push(createdPriceSet) - } - linksToCreate.push({ - productService: { - variant_id: variantId, - }, - pricingService: { - price_set_id: priceSetId, - }, - }) + linksToCreate.push({ + productService: { + variant_id: variantId, + }, + pricingService: { + price_set_id: priceSetId, + }, + }) + } } const createdLinks = await remoteLink.create(linksToCreate) diff --git a/packages/workflows/src/helper/workflow-export.ts b/packages/workflows/src/helper/workflow-export.ts index 3b2fc8dcec70b..ed75b21d30eae 100644 --- a/packages/workflows/src/helper/workflow-export.ts +++ b/packages/workflows/src/helper/workflow-export.ts @@ -11,6 +11,7 @@ import { MedusaModule } from "@medusajs/modules-sdk" import { EOL } from "os" import { ulid } from "ulid" import { Workflows } from "../definitions" +import { SymbolWorkflowWorkflowData } from "../utils/composer" export type FlowRunOptions = { input?: TData @@ -26,7 +27,7 @@ export type WorkflowResult = { } export const exportWorkflow = ( - workflowId: Workflows, + workflowId: Workflows | string, defaultResult?: string, dataPreparation?: (data: TData) => Promise ) => { @@ -63,7 +64,7 @@ export const exportWorkflow = ( if (typeof dataPreparation === "function") { try { - const copyInput = JSON.parse(JSON.stringify(input)) + const copyInput = input ? JSON.parse(JSON.stringify(input)) : input input = await dataPreparation(copyInput as TData) } catch (err) { if (throwOnError) { @@ -97,11 +98,13 @@ export const exportWorkflow = ( if (resultFrom) { if (Array.isArray(resultFrom)) { - result = resultFrom.map( - (from) => transaction.getContext().invoke?.[from] - ) + result = resultFrom.map((from) => { + const res = transaction.getContext().invoke?.[from] + return res?.__type === SymbolWorkflowWorkflowData ? res.output : res + }) } else { - result = transaction.getContext().invoke?.[resultFrom] + const res = transaction.getContext().invoke?.[resultFrom] + result = res?.__type === SymbolWorkflowWorkflowData ? res.output : res } } diff --git a/packages/workflows/src/index.ts b/packages/workflows/src/index.ts index 2816d42f49232..e60ea511b25cb 100644 --- a/packages/workflows/src/index.ts +++ b/packages/workflows/src/index.ts @@ -2,3 +2,5 @@ export * from "./definition" export * from "./definitions" export * as Handlers from "./handlers" export * from "./helper" +export * from "./utils/composer" +export * as Composer from "./utils/composer" diff --git a/packages/workflows/src/utils/composer/create-step.ts b/packages/workflows/src/utils/composer/create-step.ts new file mode 100644 index 0000000000000..e647ab60d4eb8 --- /dev/null +++ b/packages/workflows/src/utils/composer/create-step.ts @@ -0,0 +1,295 @@ +import { + resolveValue, + StepResponse, + SymbolMedusaWorkflowComposerContext, + SymbolWorkflowStep, + SymbolWorkflowStepBind, + SymbolWorkflowStepResponse, + SymbolWorkflowWorkflowData, +} from "./helpers" +import { + CreateWorkflowComposerContext, + StepExecutionContext, + StepFunction, + StepFunctionResult, + WorkflowData, +} from "./type" +import { proxify } from "./helpers/proxy" + +/** + * The type of invocation function passed to a step. + * + * @typeParam TInput - The type of the input that the function expects. + * @typeParam TOutput - The type of the output that the function returns. + * @typeParam TCompensateInput - The type of the input that the compensation function expects. + * + * @returns The expected output based on the type parameter `TOutput`. + */ +type InvokeFn = ( + /** + * The input of the step. + */ + input: { + [Key in keyof TInput]: TInput[Key] + }, + /** + * The step's context. + */ + context: StepExecutionContext +) => + | void + | StepResponse< + TOutput, + TCompensateInput extends undefined ? TOutput : TCompensateInput + > + | Promise> + +/** + * The type of compensation function passed to a step. + * + * @typeParam T - + * The type of the argument passed to the compensation function. If not specified, then it will be the same type as the invocation function's output. + * + * @returns There's no expected type to be returned by the compensation function. + */ +type CompensateFn = ( + /** + * The argument passed to the compensation function. + */ + input: T | undefined, + /** + * The step's context. + */ + context: StepExecutionContext +) => unknown | Promise + +interface ApplyStepOptions< + TStepInputs extends { + [K in keyof TInvokeInput]: WorkflowData + }, + TInvokeInput extends object, + TInvokeResultOutput, + TInvokeResultCompensateInput +> { + stepName: string + input: TStepInputs + invokeFn: InvokeFn< + TInvokeInput, + TInvokeResultOutput, + TInvokeResultCompensateInput + > + compensateFn?: CompensateFn +} + +/** + * @internal + * + * Internal function to create the invoke and compensate handler for a step. + * This is where the inputs and context are passed to the underlying invoke and compensate function. + * + * @param stepName + * @param input + * @param invokeFn + * @param compensateFn + */ +function applyStep< + TInvokeInput extends object, + TStepInput extends { + [K in keyof TInvokeInput]: WorkflowData + }, + TInvokeResultOutput, + TInvokeResultCompensateInput +>({ + stepName, + input, + invokeFn, + compensateFn, +}: ApplyStepOptions< + TStepInput, + TInvokeInput, + TInvokeResultOutput, + TInvokeResultCompensateInput +>): StepFunctionResult { + return function (this: CreateWorkflowComposerContext) { + if (!this.workflowId) { + throw new Error( + "createStep must be used inside a createWorkflow definition" + ) + } + + const handler = { + invoke: async (transactionContext) => { + const executionContext: StepExecutionContext = { + container: transactionContext.container, + metadata: transactionContext.metadata, + context: transactionContext.context, + } + + const argInput = await resolveValue(input, transactionContext) + const stepResponse: StepResponse = await invokeFn.apply( + this, + [argInput, executionContext] + ) + + const stepResponseJSON = + stepResponse?.__type === SymbolWorkflowStepResponse + ? stepResponse.toJSON() + : stepResponse + + return { + __type: SymbolWorkflowWorkflowData, + output: stepResponseJSON, + } + }, + compensate: compensateFn + ? async (transactionContext) => { + const executionContext: StepExecutionContext = { + container: transactionContext.container, + metadata: transactionContext.metadata, + context: transactionContext.context, + } + + const stepOutput = transactionContext.invoke[stepName]?.output + const invokeResult = + stepOutput?.__type === SymbolWorkflowStepResponse + ? stepOutput.compensateInput && + JSON.parse(JSON.stringify(stepOutput.compensateInput)) + : stepOutput && JSON.parse(JSON.stringify(stepOutput)) + + const args = [invokeResult, executionContext] + const output = await compensateFn.apply(this, args) + return { + output, + } + } + : undefined, + } + + this.flow.addAction(stepName, { + noCompensation: !compensateFn, + }) + this.handlers.set(stepName, handler) + + const ret = { + __type: SymbolWorkflowStep, + __step__: stepName, + } + + return proxify(ret) + } +} + +/** + * This function creates a {@link StepFunction} that can be used as a step in a workflow constructed by the {@link createWorkflow} function. + * + * @typeParam TInvokeInput - The type of the expected input parameter to the invocation function. + * @typeParam TInvokeResultOutput - The type of the expected output parameter of the invocation function. + * @typeParam TInvokeResultCompensateInput - The type of the expected input parameter to the compensation function. + * + * @returns A step function to be used in a workflow. + * + * @example + * import { + * createStep, + * StepResponse, + * StepExecutionContext, + * WorkflowData + * } from "@medusajs/workflows" + * + * interface CreateProductInput { + * title: string + * } + * + * export const createProductStep = createStep( + * "createProductStep", + * async function ( + * input: CreateProductInput, + * context + * ) { + * const productService = context.container.resolve( + * "productService" + * ) + * const product = await productService.create(input) + * return new StepResponse({ + * product + * }, { + * product_id: product.id + * }) + * }, + * async function ( + * input, + * context + * ) { + * const productService = context.container.resolve( + * "productService" + * ) + * await productService.delete(input.product_id) + * } + * ) + */ +export function createStep< + TInvokeInput extends object, + TInvokeResultOutput, + TInvokeResultCompensateInput +>( + /** + * The name of the step. + */ + name: string, + /** + * An invocation function that will be executed when the workflow is executed. The function must return an instance of {@link StepResponse}. The constructor of {@link StepResponse} + * accepts the output of the step as a first argument, and optionally as a second argument the data to be passed to the compensation function as a parameter. + */ + invokeFn: InvokeFn< + TInvokeInput, + TInvokeResultOutput, + TInvokeResultCompensateInput + >, + /** + * A compensation function that's executed if an error occurs in the workflow. It's used to roll-back actions when errors occur. + * It accepts as a parameter the second argument passed to the constructor of the {@link StepResponse} instance returned by the invocation function. If the + * invocation function doesn't pass the second argument to `StepResponse` constructor, the compensation function receives the first argument + * passed to the `StepResponse` constructor instead. + */ + compensateFn?: CompensateFn +): StepFunction { + const stepName = name ?? invokeFn.name + + const returnFn = function (input: { + [K in keyof TInvokeInput]: WorkflowData + }): WorkflowData { + if (!global[SymbolMedusaWorkflowComposerContext]) { + throw new Error( + "createStep must be used inside a createWorkflow definition" + ) + } + + const stepBinder = ( + global[ + SymbolMedusaWorkflowComposerContext + ] as CreateWorkflowComposerContext + ).stepBinder + + return stepBinder( + applyStep< + TInvokeInput, + { [K in keyof TInvokeInput]: WorkflowData }, + TInvokeResultOutput, + TInvokeResultCompensateInput + >({ + stepName, + input, + invokeFn, + compensateFn, + }) + ) + } + + returnFn.__type = SymbolWorkflowStepBind + returnFn.__step__ = stepName + + return returnFn as unknown as StepFunction +} diff --git a/packages/workflows/src/utils/composer/create-workflow.ts b/packages/workflows/src/utils/composer/create-workflow.ts new file mode 100644 index 0000000000000..a2c01e3cdc027 --- /dev/null +++ b/packages/workflows/src/utils/composer/create-workflow.ts @@ -0,0 +1,263 @@ +import { + LocalWorkflow, + WorkflowHandler, + WorkflowManager, +} from "@medusajs/orchestration" +import { LoadedModule, MedusaContainer } from "@medusajs/types" +import { exportWorkflow, FlowRunOptions, WorkflowResult } from "../../helper" +import { + CreateWorkflowComposerContext, + WorkflowData, + WorkflowDataProperties, +} from "./type" +import { + resolveValue, + SymbolInputReference, + SymbolMedusaWorkflowComposerContext, + SymbolWorkflowStep, +} from "./helpers" +import { proxify } from "./helpers/proxy" + +global[SymbolMedusaWorkflowComposerContext] = null + +/** + * An exported workflow, which is the type of a workflow constructed by the {@link createWorkflow} function. The exported workflow can be invoked to create + * an executable workflow, optionally within a specified container. So, to execute the workflow, you must invoke the exported workflow, then run the + * `run` method of the exported workflow. + * + * @example + * To execute a workflow: + * + * ```ts + * myWorkflow() + * .run({ + * input: { + * name: "John" + * } + * }) + * .then(({ result }) => { + * console.log(result) + * }) + * ``` + * + * To specify the container of the workflow, you can pass it as an argument to the call of the exported workflow. This is necessary when executing the workflow + * within a Medusa resource such as an API Route or a Subscriber. + * + * For example: + * + * ```ts + * import type { + * MedusaRequest, + * MedusaResponse + * } from "@medusajs/medusa"; + * import myWorkflow from "../../../workflows/hello-world"; + * + * export async function GET( + * req: MedusaRequest, + * res: MedusaResponse + * ) { + * const { result } = await myWorkflow(req.scope) + * .run({ + * input: { + * name: req.query.name as string + * } + * }) + * + * res.send(result) + * } + * ``` + */ +type ReturnWorkflow> = { + ( + container?: LoadedModule[] | MedusaContainer + ): Omit & { + run: ( + args?: FlowRunOptions< + TDataOverride extends undefined ? TData : TDataOverride + > + ) => Promise< + WorkflowResult< + TResultOverride extends undefined ? TResult : TResultOverride + > + > + } +} & THooks + +/** + * This function creates a workflow with the provided name and a constructor function. + * The constructor function builds the workflow from steps created by the {@link createStep} function. + * The returned workflow is an exported workflow of type {@link ReturnWorkflow}, meaning it's not executed right away. To execute it, + * invoke the exported workflow, then run its `run` method. + * + * @typeParam TData - The type of the input passed to the composer function. + * @typeParam TResult - The type of the output returned by the composer function. + * @typeParam THooks - The type of hooks defined in the workflow. + * + * @returns The created workflow. You can later execute the workflow by invoking it, then using its `run` method. + * + * @example + * import { createWorkflow } from "@medusajs/workflows" + * import { MedusaRequest, MedusaResponse, Product } from "@medusajs/medusa" + * import { + * createProductStep, + * getProductStep, + * createPricesStep + * } from "./steps" + * + * interface WorkflowInput { + * title: string + * } + * + * const myWorkflow = createWorkflow< + * WorkflowInput, + * Product + * >("my-workflow", (input) => { + * // Everything here will be executed and resolved later + * // during the execution. Including the data access. + * + * const product = createProductStep(input) + * const prices = createPricesStep(product) + * return getProductStep(product.id) + * } + * ) + * + * export async function GET( + * req: MedusaRequest, + * res: MedusaResponse + * ) { + * const { result: product } = await myWorkflow(req.scope) + * .run({ + * input: { + * title: "Shirt" + * } + * }) + * + * res.json({ + * product + * }) + * } + */ + +export function createWorkflow< + TData, + TResult, + THooks extends Record = Record +>( + /** + * The name of the workflow. + */ + name: string, + /** + * The constructor function that is executed when the `run` method in {@link ReturnWorkflow} is used. + * The function can't be an arrow function or an asynchronus function. It also can't directly manipulate data. + * You'll have to use the {@link transform} function if you need to directly manipulate data. + */ + composer: (input: WorkflowData) => + | void + | WorkflowData + | { + [K in keyof TResult]: + | WorkflowData + | WorkflowDataProperties + } +): ReturnWorkflow { + const handlers: WorkflowHandler = new Map() + + if (WorkflowManager.getWorkflow(name)) { + WorkflowManager.unregister(name) + } + + WorkflowManager.register(name, undefined, handlers) + + const context: CreateWorkflowComposerContext = { + workflowId: name, + flow: WorkflowManager.getTransactionDefinition(name), + handlers, + hooks_: [], + hooksCallback_: {}, + hookBinder: (name, fn) => { + context.hooks_.push(name) + return fn(context) + }, + stepBinder: (fn) => { + return fn.bind(context)() + }, + parallelizeBinder: (fn) => { + return fn.bind(context)() + }, + } + + global[SymbolMedusaWorkflowComposerContext] = context + + const inputPlaceHolder = proxify({ + __type: SymbolInputReference, + __step__: "", + }) + + const returnedStep = composer.apply(context, [inputPlaceHolder]) + + delete global[SymbolMedusaWorkflowComposerContext] + + WorkflowManager.update(name, context.flow, handlers) + + const workflow = exportWorkflow(name) + + const mainFlow = ( + container?: LoadedModule[] | MedusaContainer + ) => { + const workflow_ = workflow(container) + const originalRun = workflow_.run + + workflow_.run = (async ( + args?: FlowRunOptions< + TDataOverride extends undefined ? TData : TDataOverride + > + ): Promise< + WorkflowResult< + TResultOverride extends undefined ? TResult : TResultOverride + > + > => { + args ??= {} + args.resultFrom ??= + returnedStep?.__type === SymbolWorkflowStep + ? returnedStep.__step__ + : undefined + + // Forwards the input to the ref object on composer.apply + const workflowResult = (await originalRun( + args + )) as unknown as WorkflowResult< + TResultOverride extends undefined ? TResult : TResultOverride + > + + workflowResult.result = await resolveValue( + workflowResult.result || returnedStep, + workflowResult.transaction.getContext() + ) + + return workflowResult + }) as any + + return workflow_ + } + + let shouldRegisterHookHandler = true + + for (const hook of context.hooks_) { + mainFlow[hook] = (fn) => { + context.hooksCallback_[hook] ??= [] + + if (!shouldRegisterHookHandler) { + console.warn( + `A hook handler has already been registered for the ${hook} hook. The current handler registration will be skipped.` + ) + return + } + + context.hooksCallback_[hook].push(fn) + shouldRegisterHookHandler = false + } + } + + return mainFlow as ReturnWorkflow +} diff --git a/packages/workflows/src/utils/composer/helpers/index.ts b/packages/workflows/src/utils/composer/helpers/index.ts new file mode 100644 index 0000000000000..2636ee016ffcc --- /dev/null +++ b/packages/workflows/src/utils/composer/helpers/index.ts @@ -0,0 +1,3 @@ +export * from "./step-response" +export * from "./symbol" +export * from "./resolve-value" \ No newline at end of file diff --git a/packages/workflows/src/utils/composer/helpers/proxy.ts b/packages/workflows/src/utils/composer/helpers/proxy.ts new file mode 100644 index 0000000000000..68ca47b2f3359 --- /dev/null +++ b/packages/workflows/src/utils/composer/helpers/proxy.ts @@ -0,0 +1,28 @@ +import { transform } from "../transform" +import { WorkflowData, WorkflowTransactionContext } from "../type" +import { SymbolInputReference, SymbolWorkflowStepTransformer } from "./symbol" +import { resolveValue } from "./resolve-value" + +export function proxify(obj: WorkflowData): T { + return new Proxy(obj, { + get(target: any, prop: string | symbol): any { + if (prop in target) { + return target[prop] + } + + return transform(target[prop], async function (input, context) { + const { invoke } = context as WorkflowTransactionContext + let output = + target.__type === SymbolInputReference || + target.__type === SymbolWorkflowStepTransformer + ? target + : invoke?.[obj.__step__]?.output + + output = await resolveValue(output, context) + output = output?.[prop] + + return output && JSON.parse(JSON.stringify(output)) + }) + }, + }) as unknown as T +} diff --git a/packages/workflows/src/utils/composer/helpers/resolve-value.ts b/packages/workflows/src/utils/composer/helpers/resolve-value.ts new file mode 100644 index 0000000000000..c5fb131771b81 --- /dev/null +++ b/packages/workflows/src/utils/composer/helpers/resolve-value.ts @@ -0,0 +1,74 @@ +import { promiseAll } from "@medusajs/utils" +import { + SymbolInputReference, + SymbolWorkflowHook, + SymbolWorkflowStep, + SymbolWorkflowStepResponse, + SymbolWorkflowStepTransformer, +} from "./symbol" + +async function resolveProperty(property, transactionContext) { + const { invoke: invokeRes } = transactionContext + + if (property?.__type === SymbolInputReference) { + return transactionContext.payload + } else if (property?.__type === SymbolWorkflowStepTransformer) { + return await property.__resolver(transactionContext) + } else if (property?.__type === SymbolWorkflowHook) { + return await property.__value(transactionContext) + } else if (property?.__type === SymbolWorkflowStep) { + const output = invokeRes[property.__step__]?.output + if (output?.__type === SymbolWorkflowStepResponse) { + return output.output + } + + return output + } else if (property?.__type === SymbolWorkflowStepResponse) { + return property.output + } else { + return property + } +} + +/** + * @internal + */ +export async function resolveValue(input, transactionContext) { + const unwrapInput = async ( + inputTOUnwrap: Record, + parentRef: any + ) => { + if (inputTOUnwrap == null) { + return inputTOUnwrap + } + + if (Array.isArray(inputTOUnwrap)) { + return await promiseAll( + inputTOUnwrap.map((i) => unwrapInput(i, transactionContext)) + ) + } + + if (typeof inputTOUnwrap !== "object") { + return inputTOUnwrap + } + + for (const key of Object.keys(inputTOUnwrap)) { + parentRef[key] = await resolveProperty( + inputTOUnwrap[key], + transactionContext + ) + + if (typeof parentRef[key] === "object") { + await unwrapInput(parentRef[key], parentRef[key]) + } + } + + return parentRef + } + + const result = input?.__type + ? await resolveProperty(input, transactionContext) + : await unwrapInput(input, {}) + + return result && JSON.parse(JSON.stringify(result)) +} diff --git a/packages/workflows/src/utils/composer/helpers/step-response.ts b/packages/workflows/src/utils/composer/helpers/step-response.ts new file mode 100644 index 0000000000000..a0ccaff81e337 --- /dev/null +++ b/packages/workflows/src/utils/composer/helpers/step-response.ts @@ -0,0 +1,69 @@ +import { SymbolWorkflowStepResponse } from "./symbol" + +/** + * This class is used to create the response returned by a step. A step return its data by returning an instance of `StepResponse`. + * + * @typeParam TOutput - The type of the output of the step. + * @typeParam TCompensateInput - + * The type of the compensation input. If the step doesn't specify any compensation input, then the type of `TCompensateInput` is the same + * as that of `TOutput`. + */ +export class StepResponse { + readonly #__type = SymbolWorkflowStepResponse + readonly #output: TOutput + readonly #compensateInput?: TCompensateInput + + /** + * The constructor of the StepResponse + * + * @typeParam TOutput - The type of the output of the step. + * @typeParam TCompensateInput - + * The type of the compensation input. If the step doesn't specify any compensation input, then the type of `TCompensateInput` is the same + * as that of `TOutput`. + */ + constructor( + /** + * The output of the step. + */ + output: TOutput, + /** + * The input to be passed as a parameter to the step's compensation function. If not provided, the `output` will be provided instead. + */ + compensateInput?: TCompensateInput + ) { + this.#output = output + this.#compensateInput = (compensateInput ?? output) as TCompensateInput + } + + /** + * @internal + */ + get __type() { + return this.#__type + } + + /** + * @internal + */ + get output(): TOutput { + return this.#output + } + + /** + * @internal + */ + get compensateInput(): TCompensateInput { + return this.#compensateInput as TCompensateInput + } + + /** + * @internal + */ + toJSON() { + return { + __type: this.#__type, + output: this.#output, + compensateInput: this.#compensateInput, + } + } +} diff --git a/packages/workflows/src/utils/composer/helpers/symbol.ts b/packages/workflows/src/utils/composer/helpers/symbol.ts new file mode 100644 index 0000000000000..8ec8177d7f28d --- /dev/null +++ b/packages/workflows/src/utils/composer/helpers/symbol.ts @@ -0,0 +1,12 @@ +export const SymbolMedusaWorkflowComposerContext = Symbol.for( + "MedusaWorkflowComposerContext" +) +export const SymbolInputReference = Symbol.for("WorkflowInputReference") +export const SymbolWorkflowStep = Symbol.for("WorkflowStep") +export const SymbolWorkflowHook = Symbol.for("WorkflowHook") +export const SymbolWorkflowWorkflowData = Symbol.for("WorkflowWorkflowData") +export const SymbolWorkflowStepResponse = Symbol.for("WorkflowStepResponse") +export const SymbolWorkflowStepBind = Symbol.for("WorkflowStepBind") +export const SymbolWorkflowStepTransformer = Symbol.for( + "WorkflowStepTransformer" +) diff --git a/packages/workflows/src/utils/composer/hook.ts b/packages/workflows/src/utils/composer/hook.ts new file mode 100644 index 0000000000000..8fa91c8028a8c --- /dev/null +++ b/packages/workflows/src/utils/composer/hook.ts @@ -0,0 +1,136 @@ +import { + resolveValue, + SymbolMedusaWorkflowComposerContext, + SymbolWorkflowHook, +} from "./helpers" +import { + CreateWorkflowComposerContext, + StepExecutionContext, + WorkflowData, +} from "./type" + +/** + * + * @ignore + * + * This function allows you to add hooks in your workflow that provide access to some data. Then, consumers of that workflow can add a handler function that performs + * an action with the provided data or modify it. + * + * For example, in a "create product" workflow, you may add a hook after the product is created, providing access to the created product. + * Then, developers using that workflow can hook into that point to access the product, modify its attributes, then return the updated product. + * + * @typeParam TOutput - The expected output of the hook's handler function. + * @returns The output of handler functions of this hook. If there are no handler functions, the output is `undefined`. + * + * @example + * import { + * createWorkflow, + * StepExecutionContext, + * hook, + * transform + * } from "@medusajs/workflows" + * import { + * createProductStep, + * getProductStep, + * createPricesStep + * } from "./steps" + * import { + * MedusaRequest, + * MedusaResponse, + * Product, ProductService + * } from "@medusajs/medusa" + * + * interface WorkflowInput { + * title: string + * } + * + * const myWorkflow = createWorkflow< + * WorkflowInput, + * Product + * >("my-workflow", + * function (input) { + * const product = createProductStep(input) + * + * const hookProduct = hook("createdProductHook", product) + * + * const newProduct = transform({ + * product, + * hookProduct + * }, (input) => { + * return input.hookProduct || input.product + * }) + * + * const prices = createPricesStep(newProduct) + * + * return getProductStep(product.id) + * } + * ) + * + * myWorkflow.createdProductHook( + * async (product, context: StepExecutionContext) => { + * const productService: ProductService = context.container.resolve("productService") + * + * const updatedProduct = await productService.update(product.id, { + * description: "a cool shirt" + * }) + * + * return updatedProduct + * }) + * + * export async function POST( + * req: MedusaRequest, + * res: MedusaResponse + * ) { + * const { result: product } = await myWorkflow(req.scope) + * .run({ + * input: { + * title: req.body.title + * } + * }) + * + * res.json({ + * product + * }) + * } + */ +export function hook( + /** + * The name of the hook. This will be used by the consumer to add a handler method for the hook. + */ + name: string, + /** + * The data that a handler function receives as a parameter. + */ + value: any +): WorkflowData { + const hookBinder = ( + global[SymbolMedusaWorkflowComposerContext] as CreateWorkflowComposerContext + ).hookBinder + + return hookBinder(name, function (context) { + return { + __value: async function (transactionContext) { + const executionContext: StepExecutionContext = { + container: transactionContext.container, + metadata: transactionContext.metadata, + context: transactionContext.context, + } + + const allValues = await resolveValue(value, transactionContext) + const stepValue = allValues + ? JSON.parse(JSON.stringify(allValues)) + : allValues + + let finalResult + const functions = context.hooksCallback_[name] + for (let i = 0; i < functions.length; i++) { + const fn = functions[i] + const arg = i === 0 ? stepValue : finalResult + finalResult = await fn.apply(fn, [arg, executionContext]) + } + return finalResult + }, + __type: SymbolWorkflowHook, + } + }) +} diff --git a/packages/workflows/src/utils/composer/index.ts b/packages/workflows/src/utils/composer/index.ts new file mode 100644 index 0000000000000..485d8451cc6f4 --- /dev/null +++ b/packages/workflows/src/utils/composer/index.ts @@ -0,0 +1,9 @@ +export * from "./create-step" +export * from "./create-workflow" +export * from "./hook" +export * from "./parallelize" +export * from "./helpers/resolve-value" +export * from "./helpers/symbol" +export * from "./helpers/step-response" +export * from "./transform" +export * from "./type" diff --git a/packages/workflows/src/utils/composer/parallelize.ts b/packages/workflows/src/utils/composer/parallelize.ts new file mode 100644 index 0000000000000..fdc8ed50b399a --- /dev/null +++ b/packages/workflows/src/utils/composer/parallelize.ts @@ -0,0 +1,70 @@ +import { CreateWorkflowComposerContext, WorkflowData } from "./type" +import { SymbolMedusaWorkflowComposerContext } from "./helpers" + +/** + * This function is used to run multiple steps in parallel. The result of each step will be returned as part of the result array. + * + * @typeParam TResult - The type of the expected result. + * + * @returns The step results. The results are ordered in the array by the order they're passed in the function's parameter. + * + * @example + * ```ts + * import { + * createWorkflow, + * parallelize + * } from "@medusajs/workflows" + * import { + * createProductStep, + * getProductStep, + * createPricesStep, + * attachProductToSalesChannelStep + * } from "./steps" + * + * interface WorkflowInput { + * title: string + * } + * + * const myWorkflow = createWorkflow< + * WorkflowInput, + * Product + * >("my-workflow", (input) => { + * const product = createProductStep(input) + * + * const [prices, productSalesChannel] = parallelize( + * createPricesStep(product), + * attachProductToSalesChannelStep(product) + * ) + * + * const id = product.id + * return getProductStep(product.id) + * } + * ) + */ +export function parallelize( + ...steps: TResult +): TResult { + if (!global[SymbolMedusaWorkflowComposerContext]) { + throw new Error( + "parallelize must be used inside a createWorkflow definition" + ) + } + + const parallelizeBinder = ( + global[SymbolMedusaWorkflowComposerContext] as CreateWorkflowComposerContext + ).parallelizeBinder + + const resultSteps = steps.map((step) => step) + + return parallelizeBinder(function ( + this: CreateWorkflowComposerContext + ) { + const stepOntoMerge = steps.shift()! + this.flow.mergeActions( + stepOntoMerge.__step__, + ...steps.map((step) => step.__step__) + ) + + return resultSteps as unknown as TResult + }) +} diff --git a/packages/workflows/src/utils/composer/transform.ts b/packages/workflows/src/utils/composer/transform.ts new file mode 100644 index 0000000000000..03a97d3c6ab68 --- /dev/null +++ b/packages/workflows/src/utils/composer/transform.ts @@ -0,0 +1,193 @@ +import { resolveValue, SymbolWorkflowStepTransformer } from "./helpers" +import { StepExecutionContext, WorkflowData } from "./type" +import { proxify } from "./helpers/proxy" + +type Func1 = ( + input: T extends WorkflowData + ? U + : T extends object + ? { [K in keyof T]: T[K] extends WorkflowData ? U : T[K] } + : {}, + context: StepExecutionContext +) => U | Promise + +type Func = (input: T, context: StepExecutionContext) => U | Promise + +/** + * + * This function transforms the output of other utility functions. + * + * For example, if you're using the value(s) of some step(s) as an input to a later step. As you can't directly manipulate data in the workflow constructor function passed to {@link createWorkflow}, + * the `transform` function provides access to the runtime value of the step(s) output so that you can manipulate them. + * + * Another example is if you're using the runtime value of some step(s) as the output of a workflow. + * + * If you're also retrieving the output of a hook and want to check if its value is set, you must use a workflow to get the runtime value of that hook. + * + * @returns There's no expected value to be returned by the `transform` function. + * + * @example + * import { + * createWorkflow, + * transform + * } from "@medusajs/workflows" + * import { step1, step2 } from "./steps" + * + * type WorkflowInput = { + * name: string + * } + * + * type WorkflowOutput = { + * message: string + * } + * + * const myWorkflow = createWorkflow< + * WorkflowInput, + * WorkflowOutput + * > + * ("hello-world", (input) => { + * const str1 = step1(input) + * const str2 = step2(input) + * + * return transform({ + * str1, + * str2 + * }, (input) => ({ + * message: `${input.str1}${input.str2}` + * })) + * }) + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + /** + * The output(s) of other step functions. + */ + values: T, + /** + * The transform function used to perform action on the runtime values of the provided `values`. + */ + ...func: + | [Func1] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] + | [Func1, Func, Func] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] + | [Func1, Func, Func] + | [Func1, Func, Func, Func] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] + | [Func1, Func, Func] + | [Func1, Func, Func, Func] + | [Func1, Func, Func, Func, Func] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] + | [Func1, Func, Func] + | [Func1, Func, Func, Func] + | [Func1, Func, Func, Func, Func] + | [Func1, Func, Func, Func, Func, Func] +): WorkflowData + +/** + * @internal + */ +// prettier-ignore +// eslint-disable-next-line max-len +export function transform( + values: T, + ...func: + | [Func1] + | [Func1, Func] + | [Func1, Func, Func] + | [Func1, Func, Func, Func] + | [Func1, Func, Func, Func, Func] + | [Func1, Func, Func, Func, Func, Func] + | [Func1, Func, Func, Func, Func, Func, Func] +): WorkflowData + +export function transform( + values: any | any[], + ...functions: Function[] +): unknown { + const ret = { + __type: SymbolWorkflowStepTransformer, + __resolver: undefined, + } + + const returnFn = async function (transactionContext): Promise { + const allValues = await resolveValue(values, transactionContext) + const stepValue = allValues + ? JSON.parse(JSON.stringify(allValues)) + : allValues + + let finalResult + for (let i = 0; i < functions.length; i++) { + const fn = functions[i] + const arg = i === 0 ? stepValue : finalResult + + finalResult = await fn.apply(fn, [arg, transactionContext]) + } + + return finalResult + } + + const proxyfiedRet = proxify( + ret as unknown as WorkflowData + ) + proxyfiedRet.__resolver = returnFn as any + + return proxyfiedRet +} diff --git a/packages/workflows/src/utils/composer/type.ts b/packages/workflows/src/utils/composer/type.ts new file mode 100644 index 0000000000000..f6f019d9e8151 --- /dev/null +++ b/packages/workflows/src/utils/composer/type.ts @@ -0,0 +1,88 @@ +import { + OrchestratorBuilder, + TransactionContext as OriginalWorkflowTransactionContext, + TransactionPayload, + WorkflowHandler, +} from "@medusajs/orchestration" +import { Context, MedusaContainer } from "@medusajs/types" + +export type StepFunctionResult = + (this: CreateWorkflowComposerContext) => TOutput extends [] + ? [ + ...WorkflowData<{ + [K in keyof TOutput]: TOutput[number][K] + }>[] + ] + : WorkflowData<{ [K in keyof TOutput]: TOutput[K] }> + +/** + * A step function to be used in a workflow. + * + * @typeParam TInput - The type of the input of the step. + * @typeParam TOutput - The type of the output of the step. + */ +export type StepFunction = { + (input: { [K in keyof TInput]: WorkflowData }): WorkflowData<{ + [K in keyof TOutput]: TOutput[K] + }> +} & WorkflowDataProperties<{ + [K in keyof TOutput]: TOutput[K] +}> + +export type WorkflowDataProperties = { + __type: Symbol + __step__: string +} + +/** + * This type is used to encapsulate the input or output type of all utils. + * + * @typeParam T - The type of a step's input or result. + */ +export type WorkflowData = (T extends object + ? { + [Key in keyof T]: WorkflowData + } + : WorkflowDataProperties) & + WorkflowDataProperties + +export type CreateWorkflowComposerContext = { + hooks_: string[] + hooksCallback_: Record + workflowId: string + flow: OrchestratorBuilder + handlers: WorkflowHandler + stepBinder: ( + fn: StepFunctionResult + ) => WorkflowData + hookBinder: ( + name: string, + fn: Function + ) => WorkflowData + parallelizeBinder: ( + fn: (this: CreateWorkflowComposerContext) => TOutput + ) => TOutput +} + +/** + * The step's context. + */ +export interface StepExecutionContext { + /** + * The container used to access resources, such as services, in the step. + */ + container: MedusaContainer + /** + * Metadata passed in the input. + */ + metadata: TransactionPayload["metadata"] + /** + * {@inheritDoc Context} + */ + context: Context +} + +export type WorkflowTransactionContext = StepExecutionContext & + OriginalWorkflowTransactionContext & { + invoke: { [key: string]: { output: any } } + } diff --git a/www/apps/docs/content/admin/quickstart.mdx b/www/apps/docs/content/admin/quickstart.mdx index 84c999462b975..5c2279e88a72e 100644 --- a/www/apps/docs/content/admin/quickstart.mdx +++ b/www/apps/docs/content/admin/quickstart.mdx @@ -165,7 +165,7 @@ You can learn more about the admin dashboard and its features in the [User Guide ## Multi-Language Support -Medusa supports multiple languages and translations. +Medusa supports multiple languages and translations. Check out available languages [here](../user-guide/tips/languages.md). Refer to [this user guide](../user-guide/users/profile.md#change-admin-language) to learn how to switch the language of the Medusa admin. diff --git a/www/apps/docs/content/admin/widgets.md b/www/apps/docs/content/admin/widgets.md index 93c18718cf830..d47f1c045ada1 100644 --- a/www/apps/docs/content/admin/widgets.md +++ b/www/apps/docs/content/admin/widgets.md @@ -1085,7 +1085,7 @@ You also export the object `config` of type `WidgetConfig`, which is another wid To test out your widget, run the following command in the root backend directory: ```bash -npx @medusajs/medusa-cli@latest develop +npx medusa develop ``` This command will build your backend and admin, then runs the backend. diff --git a/www/apps/docs/content/deployments/server/deploying-on-digital-ocean.md b/www/apps/docs/content/deployments/server/deploying-on-digital-ocean.md index 17016cddb6047..513c7eca24b25 100644 --- a/www/apps/docs/content/deployments/server/deploying-on-digital-ocean.md +++ b/www/apps/docs/content/deployments/server/deploying-on-digital-ocean.md @@ -211,7 +211,7 @@ YARN_PRODUCTION=false NODE_ENV=production ``` -:::caution +:::warning It’s highly recommended to use strong, randomly generated secrets for `JWT_SECRET` and `COOKIE_SECRET`. diff --git a/www/apps/docs/content/development/backend/prepare-environment.mdx b/www/apps/docs/content/development/backend/prepare-environment.mdx index f898968c1885a..709778687e6ca 100644 --- a/www/apps/docs/content/development/backend/prepare-environment.mdx +++ b/www/apps/docs/content/development/backend/prepare-environment.mdx @@ -14,7 +14,7 @@ This document includes the installation instructions for the tools required to u Node.js is the environment that makes it possible for Medusa to run, so you must install Node.js on your machine to start Medusa development. -:::caution +:::warning Medusa supports v16+ of Node.js. You can check your Node.js version using the following command: @@ -69,6 +69,8 @@ node -v +--- + ## Git Medusa uses Git behind the scenes when you create a new project. So, you'll have to install it on your machine to get started. @@ -99,6 +101,8 @@ Medusa uses Git behind the scenes when you create a new project. So, you'll have +--- + ## PostgreSQL The Medusa backend uses PostgreSQL to store data of your commerce system. @@ -126,6 +130,8 @@ The Medusa backend uses PostgreSQL to store data of your commerce system. +--- + ## (Optional) Medusa CLI Medusa provides a CLI tool that can aid your through your Medusa development. You can install it globally, or you can use it through `npx`. diff --git a/www/apps/docs/content/development/feature-flags/toggle.md b/www/apps/docs/content/development/feature-flags/toggle.md index 842f123004b70..9c37b37d6da6c 100644 --- a/www/apps/docs/content/development/feature-flags/toggle.md +++ b/www/apps/docs/content/development/feature-flags/toggle.md @@ -15,7 +15,7 @@ If a feature flag is enabled/disabled by default, you don’t need to manually e ## Enable Feature Flags -:::caution +:::warning Features guarded by feature flags are experimental and beta features. Enable them with caution. diff --git a/www/apps/docs/content/modules/carts-and-checkout/payment.md b/www/apps/docs/content/modules/carts-and-checkout/payment.md index 31dbc630fe43b..52f734c570238 100644 --- a/www/apps/docs/content/modules/carts-and-checkout/payment.md +++ b/www/apps/docs/content/modules/carts-and-checkout/payment.md @@ -50,7 +50,7 @@ When you run your Medusa backend, the Payment Processor will be registered on yo Once the Payment Processor is added to the backend, the store operator will be able to choose using the [admin dashboard](../../admin/quickstart.mdx) the payment processors available in a region. You can alternatively do that using the [admin APIs](https://docs.medusajs.com/api/admin). These payment processors are shown to the customer at checkout as payment methods to choose from and use. -:::caution +:::warning It’s important to enable a payment processor in a region, or else the payment processor cannot be used by customers on checkout. diff --git a/www/apps/docs/content/modules/price-lists/admin/_import-prices.mdx b/www/apps/docs/content/modules/price-lists/admin/_import-prices.mdx index 446f3ee75d82c..6f025fb3e2a85 100644 --- a/www/apps/docs/content/modules/price-lists/admin/_import-prices.mdx +++ b/www/apps/docs/content/modules/price-lists/admin/_import-prices.mdx @@ -15,7 +15,7 @@ In this document, you’ll learn how to bulk import prices into a price list usi Using Medusa’s [Batch Job Admin APIs](https://docs.medusajs.com/api/admin#batch-jobs), you can import prices into a price list. -:::caution +:::warning Importing prices into a price list removes all existing prices in the price list and adds the imported prices. diff --git a/www/apps/docs/content/plugins/file-service/local.md b/www/apps/docs/content/plugins/file-service/local.md index 80a331b361893..17056f250fc22 100644 --- a/www/apps/docs/content/plugins/file-service/local.md +++ b/www/apps/docs/content/plugins/file-service/local.md @@ -49,7 +49,7 @@ const plugins = [ ] ``` -:::caution +:::warning If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used. diff --git a/www/apps/docs/content/plugins/file-service/minio.md b/www/apps/docs/content/plugins/file-service/minio.md index 3d1f25c01b2e5..ca9337b64bf39 100644 --- a/www/apps/docs/content/plugins/file-service/minio.md +++ b/www/apps/docs/content/plugins/file-service/minio.md @@ -63,7 +63,7 @@ To generate access keys for your plugin: 3. This will open a new form with randomly-generated keys. Click on the Create button. 4. A pop-up will then show the value for your Access Key and Secret Key. Copy them to use in the next section. -:::caution +:::warning You will not be able to access the Secret Key after closing the pop-up. So, make sure to store it somewhere to use later when configuring the plugin. @@ -107,7 +107,7 @@ const plugins = [ ] ``` -:::caution +:::warning If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used. diff --git a/www/apps/docs/content/plugins/file-service/s3.mdx b/www/apps/docs/content/plugins/file-service/s3.mdx index 1d644f4b11a7e..b3dfb92b0810f 100644 --- a/www/apps/docs/content/plugins/file-service/s3.mdx +++ b/www/apps/docs/content/plugins/file-service/s3.mdx @@ -152,7 +152,7 @@ S3_PREFIX= ``` -:::caution +:::warning If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used. diff --git a/www/apps/docs/content/plugins/file-service/spaces.md b/www/apps/docs/content/plugins/file-service/spaces.md index 0cb2c481f1f0d..41849bd9f75ad 100644 --- a/www/apps/docs/content/plugins/file-service/spaces.md +++ b/www/apps/docs/content/plugins/file-service/spaces.md @@ -67,7 +67,7 @@ This shows a table with the Name field editable. Enter a name for the Access Key Then, two keys will be available under the Key column of the table. The first one is the Access Key ID and the second is the Secret Access Key. Copy both as you’ll use them later. -:::caution +:::warning The secret access key will not be shown again after you leave the page. Make sure to copy it when you see it or you’ll need to re-generate a new one. @@ -124,7 +124,7 @@ const plugins = [ ] ``` -:::caution +:::warning If you have multiple storage plugins configured, the last plugin declared in the `medusa-config.js` file will be used. diff --git a/www/apps/docs/content/plugins/notifications/twilio-sms.md b/www/apps/docs/content/plugins/notifications/twilio-sms.md index 1dad43e1df0ba..76e917d1bd1ea 100644 --- a/www/apps/docs/content/plugins/notifications/twilio-sms.md +++ b/www/apps/docs/content/plugins/notifications/twilio-sms.md @@ -124,7 +124,7 @@ In the handler function, you resolve the `twilioSmsService` and `orderService` u The `sendSms` method of the Twilio service accepts an object of parameters. These parameters are based on Twilio’s SMS APIs. You can check their [API documentation](https://www.twilio.com/docs/sms/api/message-resource#create-a-message-resource) for more fields that you can add. -:::caution +:::warning If you’re on a Twilio trial make sure that the phone number you entered on checkout is a [verified Twilio number on your console](https://console.twilio.com/us1/develop/phone-numbers/manage/verified). diff --git a/www/apps/docs/content/references/entities/classes/Product.mdx b/www/apps/docs/content/references/entities/classes/Product.mdx index f34e1f91d3b25..a449babff630c 100644 --- a/www/apps/docs/content/references/entities/classes/Product.mdx +++ b/www/apps/docs/content/references/entities/classes/Product.mdx @@ -83,6 +83,15 @@ A product is a saleable item that holds general information such as name or desc "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/entities/classes/ProductCategory.mdx b/www/apps/docs/content/references/entities/classes/ProductCategory.mdx index e8858324325f6..e304e2cdcbea4 100644 --- a/www/apps/docs/content/references/entities/classes/ProductCategory.mdx +++ b/www/apps/docs/content/references/entities/classes/ProductCategory.mdx @@ -82,6 +82,15 @@ A product category can be used to categorize products into a hierarchy of catego "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -210,6 +219,15 @@ A product category can be used to categorize products into a hierarchy of catego "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/internal/interfaces/internal.ICacheService.mdx b/www/apps/docs/content/references/js-client/CacheTypes/interfaces/internal.internal-1.CacheTypes.ICacheService.mdx similarity index 100% rename from www/apps/docs/content/references/js-client/internal/interfaces/internal.ICacheService.mdx rename to www/apps/docs/content/references/js-client/CacheTypes/interfaces/internal.internal-1.CacheTypes.ICacheService.mdx diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.ConfigModule.mdx b/www/apps/docs/content/references/js-client/CommonTypes/types/internal.internal-1.CommonTypes.ConfigModule.mdx similarity index 67% rename from www/apps/docs/content/references/js-client/internal/types/internal.ConfigModule.mdx rename to www/apps/docs/content/references/js-client/CommonTypes/types/internal.internal-1.CommonTypes.ConfigModule.mdx index e7e0db210342c..1935124eb1908 100644 --- a/www/apps/docs/content/references/js-client/internal/types/internal.ConfigModule.mdx +++ b/www/apps/docs/content/references/js-client/CommonTypes/types/internal.internal-1.CommonTypes.ConfigModule.mdx @@ -20,7 +20,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "modules", - "type": "`Record`", + "type": "`Record`", "description": "", "optional": true, "defaultValue": "", @@ -38,7 +38,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "projectConfig", - "type": "[ProjectConfigOptions](../../CommonTypes/types/internal.internal-1.CommonTypes.ProjectConfigOptions.mdx)", + "type": "[ProjectConfigOptions](internal.internal-1.CommonTypes.ProjectConfigOptions.mdx)", "description": "", "optional": false, "defaultValue": "", diff --git a/www/apps/docs/content/references/js-client/internal/interfaces/internal.IEventBusModuleService.mdx b/www/apps/docs/content/references/js-client/EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusModuleService.mdx similarity index 81% rename from www/apps/docs/content/references/js-client/internal/interfaces/internal.IEventBusModuleService.mdx rename to www/apps/docs/content/references/js-client/EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusModuleService.mdx index c40e45a489d93..192173c78a5a6 100644 --- a/www/apps/docs/content/references/js-client/internal/interfaces/internal.IEventBusModuleService.mdx +++ b/www/apps/docs/content/references/js-client/EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusModuleService.mdx @@ -65,7 +65,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" -`**addPrices**(data, sharedContext?): Promise<[PriceSetDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` +`**addPrices**(data, sharedContext?): Promise<[PriceSetDTO](internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` This method adds prices to multiple price sets. @@ -268,7 +268,7 @@ async function addPricesToPriceSet (priceSetId: string) { -`**addRules**(data, sharedContext?): Promise<[PriceSetDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` +`**addRules**(data, sharedContext?): Promise<[PriceSetDTO](internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` This method adds rules to multiple price sets. @@ -396,7 +396,7 @@ async function addRulesToPriceSet (priceSetId: string) { -`**create**(data, sharedContext?): Promise<[PriceSetDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` +`**create**(data, sharedContext?): Promise<[PriceSetDTO](internal.internal-1.PricingTypes.PriceSetDTO.mdx)[]>` This method is used to create multiple price sets. @@ -749,7 +749,7 @@ async function createPriceSets() { diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCategoryDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCategoryDTO.mdx index 32a56069f2bd6..1d773e50f686c 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCategoryDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCategoryDTO.mdx @@ -59,7 +59,7 @@ A product category to create. { "name": "parent_category_id", "type": "`null` \\| `string`", - "description": "The ID of the parent product category, if it has any. It may also be `null`.", + "description": "The ID of the parent product category, if it has any.", "optional": false, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCollectionDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCollectionDTO.mdx index 33558d48bd056..717b6ab2c0714 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCollectionDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductCollectionDTO.mdx @@ -32,7 +32,7 @@ A product collection to create. { "name": "product_ids", "type": "`string`[]", - "description": "", + "description": "The products to associate with the collection.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductDTO.mdx index de1f1f97c0a6a..f791426aa6839 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.CreateProductDTO.mdx @@ -149,7 +149,7 @@ A product to create. { "name": "status", "type": "[ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx)", - "description": "The status of the product. Its value can be one of the values of the enum [ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx).", + "description": "The status of the product.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductCollectionProps.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductCollectionProps.mdx index 99f84f6a1e92f..a7ecc7e3bf800 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductCollectionProps.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductCollectionProps.mdx @@ -32,7 +32,7 @@ The filters to apply on retrieved product collections. { "name": "handle", "type": "`string` \\| `string`[]", - "description": "", + "description": "The handles to filter product collections by.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductProps.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductProps.mdx index d08ca5f0ed6db..71b3e06d89d25 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductProps.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductProps.mdx @@ -41,7 +41,7 @@ The filters to apply on retrieved products. { "name": "categories.id", "type": "`string` \\| `string`[] \\| [OperatorMap](../../internal/types/internal.OperatorMap.mdx)<string>", - "description": "", + "description": "IDs to filter categories by.", "optional": true, "defaultValue": "", "expandable": false, @@ -50,7 +50,7 @@ The filters to apply on retrieved products. { "name": "categories.is_active", "type": "`boolean`", - "description": "", + "description": "Filter categories by whether they're active.", "optional": true, "defaultValue": "", "expandable": false, @@ -59,7 +59,7 @@ The filters to apply on retrieved products. { "name": "categories.is_internal", "type": "`boolean`", - "description": "", + "description": "Filter categories by whether they're internal", "optional": true, "defaultValue": "", "expandable": false, @@ -68,7 +68,7 @@ The filters to apply on retrieved products. { "name": "category_id", "type": "`string` \\| `string`[] \\| [OperatorMap](../../internal/types/internal.OperatorMap.mdx)<string>", - "description": "", + "description": "Filter a product by the IDs of their associated categories.", "optional": true, "defaultValue": "", "expandable": false, @@ -77,7 +77,7 @@ The filters to apply on retrieved products. { "name": "collection_id", "type": "`string` \\| `string`[] \\| [OperatorMap](../../internal/types/internal.OperatorMap.mdx)<string>", - "description": "Filters a product by its associated collections.", + "description": "Filters a product by the IDs of their associated collections.", "optional": true, "defaultValue": "", "expandable": false, @@ -122,7 +122,7 @@ The filters to apply on retrieved products. { "name": "tags.value", "type": "`string`[]", - "description": "", + "description": "Values to filter product tags by.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductVariantProps.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductVariantProps.mdx index 80b26da9f006f..025301cb1bc59 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductVariantProps.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.FilterableProductVariantProps.mdx @@ -50,7 +50,7 @@ The filters to apply on retrieved product variants. { "name": "options.id", "type": "`string`[]", - "description": "", + "description": "IDs to filter options by.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCategoryDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCategoryDTO.mdx index d5972fc1bdf8c..4f94202896a52 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCategoryDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCategoryDTO.mdx @@ -14,10 +14,10 @@ A product category's data. { "name": "category_children", "type": "[ProductCategoryDTO](internal.internal-1.ProductTypes.ProductCategoryDTO.mdx)[]", - "description": "The associated child categories. It may only be available if the `category_children` relation is expanded.", + "description": "The associated child categories.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -86,10 +86,10 @@ A product category's data. { "name": "parent_category", "type": "[ProductCategoryDTO](internal.internal-1.ProductTypes.ProductCategoryDTO.mdx)", - "description": "The associated parent category. It may only be available if the `parent_category` relation is expanded.", + "description": "The associated parent category.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCollectionDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCollectionDTO.mdx index 491fad90885cd..a665e6cec5d38 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCollectionDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductCollectionDTO.mdx @@ -50,10 +50,10 @@ A product collection's data. { "name": "products", "type": "[ProductDTO](internal.internal-1.ProductTypes.ProductDTO.mdx)[]", - "description": "The associated products. It may only be available if the `products` relation is expanded.", + "description": "The associated products.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductDTO.mdx index 06ae6e14de549..497eba2a26a56 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductDTO.mdx @@ -14,19 +14,19 @@ A product's data. { "name": "categories", "type": "`null` \\| [ProductCategoryDTO](internal.internal-1.ProductTypes.ProductCategoryDTO.mdx)[]", - "description": "The associated product categories. It may only be available if the `categories` relation is expanded.", + "description": "The associated product categories.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "collection", "type": "[ProductCollectionDTO](internal.internal-1.ProductTypes.ProductCollectionDTO.mdx)", - "description": "The associated product collection. It may only be available if the `collection` relation is expanded.", + "description": "The associated product collection.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -50,7 +50,7 @@ A product's data. { "name": "description", "type": "`null` \\| `string`", - "description": "The description of the product. It can possibly be `null`.", + "description": "The description of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -77,7 +77,7 @@ A product's data. { "name": "handle", "type": "`null` \\| `string`", - "description": "The handle of the product. The handle can be used to create slug URL paths. It can possibly be `null`.", + "description": "The handle of the product. The handle can be used to create slug URL paths.", "optional": true, "defaultValue": "", "expandable": false, @@ -86,7 +86,7 @@ A product's data. { "name": "height", "type": "`null` \\| `number`", - "description": "The height of the product. It can possibly be `null`.", + "description": "The height of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -95,7 +95,7 @@ A product's data. { "name": "hs_code", "type": "`null` \\| `string`", - "description": "The HS Code of the product. It can possibly be `null`.", + "description": "The HS Code of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -113,10 +113,10 @@ A product's data. { "name": "images", "type": "[ProductImageDTO](internal.internal-1.ProductTypes.ProductImageDTO.mdx)[]", - "description": "The associated product images. It may only be available if the `images` relation is expanded.", + "description": "The associated product images.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -131,7 +131,7 @@ A product's data. { "name": "length", "type": "`null` \\| `number`", - "description": "The length of the product. It can possibly be `null`.", + "description": "The length of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -140,7 +140,7 @@ A product's data. { "name": "material", "type": "`null` \\| `string`", - "description": "The material of the product. It can possibly be `null`.", + "description": "The material of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -149,7 +149,7 @@ A product's data. { "name": "metadata", "type": "`Record`", - "description": "", + "description": "Holds custom data in key-value pairs.", "optional": true, "defaultValue": "", "expandable": false, @@ -158,7 +158,7 @@ A product's data. { "name": "mid_code", "type": "`null` \\| `string`", - "description": "The MID Code of the product. It can possibly be `null`.", + "description": "The MID Code of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -167,16 +167,16 @@ A product's data. { "name": "options", "type": "[ProductOptionDTO](internal.internal-1.ProductTypes.ProductOptionDTO.mdx)[]", - "description": "The associated product options. It may only be available if the `options` relation is expanded.", + "description": "The associated product options.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "origin_country", "type": "`null` \\| `string`", - "description": "The origin country of the product. It can possibly be `null`.", + "description": "The origin country of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -185,7 +185,7 @@ A product's data. { "name": "status", "type": "[ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx)", - "description": "The status of the product. Its value can be one of the values of the enum [ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx).", + "description": "The status of the product.", "optional": false, "defaultValue": "", "expandable": false, @@ -194,7 +194,7 @@ A product's data. { "name": "subtitle", "type": "`null` \\| `string`", - "description": "The subttle of the product. It can possibly be `null`.", + "description": "The subttle of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -203,16 +203,16 @@ A product's data. { "name": "tags", "type": "[ProductTagDTO](internal.internal-1.ProductTypes.ProductTagDTO.mdx)[]", - "description": "The associated product tags. It may only be available if the `tags` relation is expanded.", + "description": "The associated product tags.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "thumbnail", "type": "`null` \\| `string`", - "description": "The URL of the product's thumbnail. It can possibly be `null`.", + "description": "The URL of the product's thumbnail.", "optional": true, "defaultValue": "", "expandable": false, @@ -230,10 +230,10 @@ A product's data. { "name": "type", "type": "[ProductTypeDTO](internal.internal-1.ProductTypes.ProductTypeDTO.mdx)[]", - "description": "The associated product type. It may only be available if the `type` relation is expanded.", + "description": "The associated product type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -248,16 +248,16 @@ A product's data. { "name": "variants", "type": "[ProductVariantDTO](internal.internal-1.ProductTypes.ProductVariantDTO.mdx)[]", - "description": "The associated product variants. It may only be available if the `variants` relation is expanded.", + "description": "The associated product variants.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "weight", "type": "`null` \\| `number`", - "description": "The weight of the product. It can possibly be `null`.", + "description": "The weight of the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -266,7 +266,7 @@ A product's data. { "name": "width", "type": "`null` \\| `number`", - "description": "", + "description": "The width of the product.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionDTO.mdx index 513f89b0df87a..9c47f4e314cd5 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionDTO.mdx @@ -41,10 +41,10 @@ A product option's data. { "name": "product", "type": "[ProductDTO](internal.internal-1.ProductTypes.ProductDTO.mdx)", - "description": "The associated product. It may only be available if the `product` relation is expanded.", + "description": "The associated product.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -59,10 +59,10 @@ A product option's data. { "name": "values", "type": "[ProductOptionValueDTO](internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx)[]", - "description": "The associated product option values. It may only be available if the `values` relation is expanded.", + "description": "The associated product option values.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] } ]} /> diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx index 88daf74255ad7..7d1d47d4fbc76 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx @@ -41,10 +41,10 @@ The product option value's data. { "name": "option", "type": "[ProductOptionDTO](internal.internal-1.ProductTypes.ProductOptionDTO.mdx)", - "description": "The associated product option. It may only be available if the `option` relation is expanded.", + "description": "The associated product option.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -59,10 +59,10 @@ The product option value's data. { "name": "variant", "type": "[ProductVariantDTO](internal.internal-1.ProductTypes.ProductVariantDTO.mdx)", - "description": "The associated product variant. It may only be available if the `variant` relation is expanded.", + "description": "The associated product variant.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] } ]} /> diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductTagDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductTagDTO.mdx index 68b335610631d..3b55544fb4e02 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductTagDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductTagDTO.mdx @@ -32,10 +32,10 @@ A product tag's data. { "name": "products", "type": "[ProductDTO](internal.internal-1.ProductTypes.ProductDTO.mdx)[]", - "description": "The associated products. It may only be available if the `products` relation is expanded.", + "description": "The associated products.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductVariantDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductVariantDTO.mdx index a786cc30854d2..2e8899d066b39 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductVariantDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.ProductVariantDTO.mdx @@ -23,7 +23,7 @@ A product variant's data. { "name": "barcode", "type": "`null` \\| `string`", - "description": "The barcode of the product variant. It can possibly be `null`.", + "description": "The barcode of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -50,7 +50,7 @@ A product variant's data. { "name": "ean", "type": "`null` \\| `string`", - "description": "The EAN of the product variant. It can possibly be `null`.", + "description": "The EAN of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -59,7 +59,7 @@ A product variant's data. { "name": "height", "type": "`null` \\| `number`", - "description": "The height of the product variant. It can possibly be `null`.", + "description": "The height of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -68,7 +68,7 @@ A product variant's data. { "name": "hs_code", "type": "`null` \\| `string`", - "description": "The HS Code of the product variant. It can possibly be `null`.", + "description": "The HS Code of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -95,7 +95,7 @@ A product variant's data. { "name": "length", "type": "`null` \\| `number`", - "description": "The length of the product variant. It can possibly be `null`.", + "description": "The length of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -113,7 +113,7 @@ A product variant's data. { "name": "material", "type": "`null` \\| `string`", - "description": "The material of the product variant. It can possibly be `null`.", + "description": "The material of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -131,7 +131,7 @@ A product variant's data. { "name": "mid_code", "type": "`null` \\| `string`", - "description": "The MID Code of the product variant. It can possibly be `null`.", + "description": "The MID Code of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -140,16 +140,16 @@ A product variant's data. { "name": "options", "type": "[ProductOptionValueDTO](internal.internal-1.ProductTypes.ProductOptionValueDTO.mdx)", - "description": "The associated product options. It may only be available if the `options` relation is expanded.", + "description": "The associated product options.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "origin_country", "type": "`null` \\| `string`", - "description": "The origin country of the product variant. It can possibly be `null`.", + "description": "The origin country of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -158,10 +158,10 @@ A product variant's data. { "name": "product", "type": "[ProductDTO](internal.internal-1.ProductTypes.ProductDTO.mdx)", - "description": "The associated product. It may only be available if the `product` relation is expanded.", + "description": "The associated product.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -176,7 +176,7 @@ A product variant's data. { "name": "sku", "type": "`null` \\| `string`", - "description": "The SKU of the product variant. It can possibly be `null`.", + "description": "The SKU of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -194,7 +194,7 @@ A product variant's data. { "name": "upc", "type": "`null` \\| `string`", - "description": "The UPC of the product variant. It can possibly be `null`.", + "description": "The UPC of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -212,7 +212,7 @@ A product variant's data. { "name": "variant_rank", "type": "`null` \\| `number`", - "description": "The ranking of the variant among other variants associated with the product. It can possibly be `null`.", + "description": "he ranking of the variant among other variants associated with the product.", "optional": true, "defaultValue": "", "expandable": false, @@ -221,7 +221,7 @@ A product variant's data. { "name": "weight", "type": "`null` \\| `number`", - "description": "The weight of the product variant. It can possibly be `null`.", + "description": "The weight of the product variant.", "optional": true, "defaultValue": "", "expandable": false, @@ -230,7 +230,7 @@ A product variant's data. { "name": "width", "type": "`null` \\| `number`", - "description": "The width of the product variant. It can possibly be `null`.", + "description": "The width of the product variant.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductCategoryDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductCategoryDTO.mdx index 3bef7a65d0bd2..a87aa5a9c2d30 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductCategoryDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductCategoryDTO.mdx @@ -59,7 +59,7 @@ The data to update in a product category. { "name": "parent_category_id", "type": "`null` \\| `string`", - "description": "The ID of the parent product category, if it has any. It may also be `null`.", + "description": "The ID of the parent product category, if it has any.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductDTO.mdx b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductDTO.mdx index 0481fb92c1e88..d92b646667c8a 100644 --- a/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductDTO.mdx +++ b/www/apps/docs/content/references/js-client/ProductTypes/interfaces/internal.internal-1.ProductTypes.UpdateProductDTO.mdx @@ -158,7 +158,7 @@ The data to update in a product. The `id` is used to identify which product to u { "name": "status", "type": "[ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx)", - "description": "The status of the product. Its value can be one of the values of the enum [ProductStatus](../enums/internal.internal-1.ProductTypes.ProductStatus.mdx).", + "description": "The status of the product.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/internal/interfaces/internal.IStockLocationService.mdx b/www/apps/docs/content/references/js-client/StockLocationTypes/interfaces/internal.internal-1.StockLocationTypes.IStockLocationService.mdx similarity index 91% rename from www/apps/docs/content/references/js-client/internal/interfaces/internal.IStockLocationService.mdx rename to www/apps/docs/content/references/js-client/StockLocationTypes/interfaces/internal.internal-1.StockLocationTypes.IStockLocationService.mdx index 7f7e414d2062e..af403389abd23 100644 --- a/www/apps/docs/content/references/js-client/internal/interfaces/internal.IStockLocationService.mdx +++ b/www/apps/docs/content/references/js-client/StockLocationTypes/interfaces/internal.internal-1.StockLocationTypes.IStockLocationService.mdx @@ -35,7 +35,7 @@ async function createStockLocation (name: string) { `", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -319,6 +328,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional set of key-value pairs to hold additional information.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -440,6 +458,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -871,6 +898,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -1100,6 +1136,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -1339,6 +1384,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -1478,6 +1532,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional set of key-value pairs to hold additional information.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -1608,6 +1671,15 @@ medusa.admin.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/classes/ProductCategoriesResource.mdx b/www/apps/docs/content/references/js-client/classes/ProductCategoriesResource.mdx index fbbd57184d7ad..3e8b9dddc5d48 100644 --- a/www/apps/docs/content/references/js-client/classes/ProductCategoriesResource.mdx +++ b/www/apps/docs/content/references/js-client/classes/ProductCategoriesResource.mdx @@ -302,6 +302,15 @@ medusa.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", @@ -541,6 +550,15 @@ medusa.productCategories "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/internal-1/interfaces/internal.internal-1.Context.mdx b/www/apps/docs/content/references/js-client/internal-1/interfaces/internal.internal-1.Context.mdx index 32d62446ef9f3..cd1f08fb8e7e4 100644 --- a/www/apps/docs/content/references/js-client/internal-1/interfaces/internal.internal-1.Context.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/interfaces/internal.internal-1.Context.mdx @@ -28,7 +28,7 @@ A shared context object that is used to share resources between the application { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -55,7 +55,7 @@ A shared context object that is used to share resources between the application { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CacheTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CacheTypes.mdx index 86bdaa0f08517..c56f149c09453 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CacheTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CacheTypes.mdx @@ -5,3 +5,7 @@ displayed_sidebar: jsClientSidebar import ParameterTypes from "@site/src/components/ParameterTypes" # CacheTypes + +## Interfaces + +- [ICacheService](../../CacheTypes/interfaces/internal.internal-1.CacheTypes.ICacheService.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CommonTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CommonTypes.mdx index b71d2073741f5..5b305fda2c6c7 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CommonTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.CommonTypes.mdx @@ -24,6 +24,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" ## Type Aliases +- [ConfigModule](../../CommonTypes/types/internal.internal-1.CommonTypes.ConfigModule.mdx) - [ExtendedFindConfig](../../CommonTypes/types/internal.internal-1.CommonTypes.ExtendedFindConfig.mdx) - [HttpCompressionOptions](../../CommonTypes/types/internal.internal-1.CommonTypes.HttpCompressionOptions.mdx) - [PartialPick](../../CommonTypes/types/internal.internal-1.CommonTypes.PartialPick.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.EventBusTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.EventBusTypes.mdx index bd1fd2516c1a9..8a7dac3b6f262 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.EventBusTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.EventBusTypes.mdx @@ -6,7 +6,15 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # EventBusTypes +## Interfaces + +- [IEventBusModuleService](../../EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusModuleService.mdx) +- [IEventBusService](../../EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusService.mdx) + ## Type Aliases +- [EmitData](../../EventBusTypes/types/internal.internal-1.EventBusTypes.EmitData.mdx) - [EventHandler](../../EventBusTypes/types/internal.internal-1.EventBusTypes.EventHandler.mdx) +- [Subscriber](../../EventBusTypes/types/internal.internal-1.EventBusTypes.Subscriber.mdx) +- [SubscriberContext](../../EventBusTypes/types/internal.internal-1.EventBusTypes.SubscriberContext.mdx) - [SubscriberDescriptor](../../EventBusTypes/types/internal.internal-1.EventBusTypes.SubscriberDescriptor.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.InventoryTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.InventoryTypes.mdx index 2eb584f3155e8..9e6425bde466a 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.InventoryTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.InventoryTypes.mdx @@ -15,5 +15,10 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [FilterableInventoryItemProps](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.FilterableInventoryItemProps.mdx) - [FilterableInventoryLevelProps](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.FilterableInventoryLevelProps.mdx) - [FilterableReservationItemProps](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.FilterableReservationItemProps.mdx) +- [IInventoryService](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.IInventoryService.mdx) - [UpdateInventoryLevelInput](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.UpdateInventoryLevelInput.mdx) - [UpdateReservationItemInput](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.UpdateReservationItemInput.mdx) + +## Type Aliases + +- [ReserveQuantityContext](../../InventoryTypes/types/internal.internal-1.InventoryTypes.ReserveQuantityContext.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.LoggerTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.LoggerTypes.mdx index 2bf5f0f4d6e96..8617f58c462f4 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.LoggerTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.LoggerTypes.mdx @@ -5,3 +5,7 @@ displayed_sidebar: jsClientSidebar import ParameterTypes from "@site/src/components/ParameterTypes" # LoggerTypes + +## Interfaces + +- [Logger](../../LoggerTypes/interfaces/internal.internal-1.LoggerTypes.Logger.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.ModulesSdkTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.ModulesSdkTypes.mdx index 01852a07237dc..0434e79060fb6 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.ModulesSdkTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.ModulesSdkTypes.mdx @@ -17,6 +17,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" ## Type Aliases +- [Constructor](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.Constructor.mdx) - [ExternalModuleDeclaration](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.ExternalModuleDeclaration.mdx) - [InternalModuleDeclaration](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.InternalModuleDeclaration.mdx) - [LinkModuleDefinition](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.LinkModuleDefinition.mdx) @@ -33,3 +34,4 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [ModuleResolution](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.ModuleResolution.mdx) - [ModuleServiceInitializeCustomDataLayerOptions](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions.mdx) - [ModulesResponse](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.ModulesResponse.mdx) +- [RemoteQueryFunction](../../ModulesSdkTypes/types/internal.internal-1.ModulesSdkTypes.RemoteQueryFunction.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.PricingTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.PricingTypes.mdx index 1105607df7945..19db1eea39007 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.PricingTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.PricingTypes.mdx @@ -43,6 +43,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [FilterablePriceSetProps](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.FilterablePriceSetProps.mdx) - [FilterablePriceSetRuleTypeProps](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.FilterablePriceSetRuleTypeProps.mdx) - [FilterableRuleTypeProps](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.FilterableRuleTypeProps.mdx) +- [IPricingModuleService](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.IPricingModuleService.mdx) - [MoneyAmountDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.MoneyAmountDTO.mdx) - [PriceListDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.PriceListDTO.mdx) - [PriceListPriceDTO](../../PricingTypes/interfaces/internal.internal-1.PricingTypes.PriceListPriceDTO.mdx) diff --git a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.StockLocationTypes.mdx b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.StockLocationTypes.mdx index a1e8da7c102ac..433f53a27ffb4 100644 --- a/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.StockLocationTypes.mdx +++ b/www/apps/docs/content/references/js-client/internal-1/modules/internal.internal-1.StockLocationTypes.mdx @@ -9,6 +9,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" ## Interfaces - [FilterableStockLocationProps](../../StockLocationTypes/interfaces/internal.internal-1.StockLocationTypes.FilterableStockLocationProps.mdx) +- [IStockLocationService](../../StockLocationTypes/interfaces/internal.internal-1.StockLocationTypes.IStockLocationService.mdx) ## Type Aliases diff --git a/www/apps/docs/content/references/js-client/internal/classes/internal.AbstractEventBusModuleService.mdx b/www/apps/docs/content/references/js-client/internal/classes/internal.AbstractEventBusModuleService.mdx index 5d1c7abb8a183..57b5736cbd4b5 100644 --- a/www/apps/docs/content/references/js-client/internal/classes/internal.AbstractEventBusModuleService.mdx +++ b/www/apps/docs/content/references/js-client/internal/classes/internal.AbstractEventBusModuleService.mdx @@ -8,7 +8,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" ## Implements -- [IEventBusModuleService](../interfaces/internal.IEventBusModuleService.mdx) +- [IEventBusModuleService](../../EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusModuleService.mdx) ## Properties @@ -101,7 +101,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" `", + "description": "An optional set of key-value pairs to hold additional information.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/internal/classes/internal.AdminPostProductCategoriesReq.mdx b/www/apps/docs/content/references/js-client/internal/classes/internal.AdminPostProductCategoriesReq.mdx index 1a6a8ededaa98..7a7195b31dc37 100644 --- a/www/apps/docs/content/references/js-client/internal/classes/internal.AdminPostProductCategoriesReq.mdx +++ b/www/apps/docs/content/references/js-client/internal/classes/internal.AdminPostProductCategoriesReq.mdx @@ -45,6 +45,15 @@ import ParameterTypes from "@site/src/components/ParameterTypes" "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional set of key-value pairs to hold additional information.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/internal/classes/internal.ProductCategory.mdx b/www/apps/docs/content/references/js-client/internal/classes/internal.ProductCategory.mdx index ab201ccba8430..4b0d863dda60c 100644 --- a/www/apps/docs/content/references/js-client/internal/classes/internal.ProductCategory.mdx +++ b/www/apps/docs/content/references/js-client/internal/classes/internal.ProductCategory.mdx @@ -74,6 +74,15 @@ A product category can be used to categorize products into a hierarchy of catego "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/js-client/internal/classes/internal.internal.EventBusService.mdx b/www/apps/docs/content/references/js-client/internal/classes/internal.internal.EventBusService.mdx index 000d6f73dd1d3..15ad724358b10 100644 --- a/www/apps/docs/content/references/js-client/internal/classes/internal.internal.EventBusService.mdx +++ b/www/apps/docs/content/references/js-client/internal/classes/internal.internal.EventBusService.mdx @@ -11,7 +11,7 @@ subscribers when events happen. Events will run asynchronously. ## Implements -- [IEventBusService](../interfaces/internal.IEventBusService.mdx) +- [IEventBusService](../../EventBusTypes/interfaces/internal.internal-1.EventBusTypes.IEventBusService.mdx) ## Properties @@ -45,7 +45,7 @@ subscribers when events happen. Events will run asynchronously. }, { "name": "config_", - "type": "[ConfigModule](../types/internal.ConfigModule.mdx)", + "type": "[ConfigModule](../../CommonTypes/types/internal.internal-1.CommonTypes.ConfigModule.mdx)", "description": "", "optional": false, "defaultValue": "", @@ -63,7 +63,7 @@ subscribers when events happen. Events will run asynchronously. }, { "name": "logger_", - "type": "[Logger](../interfaces/internal.Logger.mdx)", + "type": "[Logger](../../LoggerTypes/interfaces/internal.internal-1.LoggerTypes.Logger.mdx)", "description": "", "optional": false, "defaultValue": "", @@ -135,7 +135,7 @@ ___ diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-10.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-10.mdx index 03adc8898bc10..cd07198751541 100644 --- a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-10.mdx +++ b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-10.mdx @@ -20,7 +20,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "logger", - "type": "[Logger](../interfaces/internal.Logger.mdx)", + "type": "[Logger](../../LoggerTypes/interfaces/internal.internal-1.LoggerTypes.Logger.mdx)", "description": "", "optional": false, "defaultValue": "", diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-18.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-18.mdx index 522c0f5094a1a..5067043fb993b 100644 --- a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-18.mdx +++ b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-18.mdx @@ -101,7 +101,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "inventoryService", - "type": "[IInventoryService](../interfaces/internal.IInventoryService.mdx)", + "type": "[IInventoryService](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.IInventoryService.mdx)", "description": "", "optional": false, "defaultValue": "", diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-19.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-19.mdx index 1898062c2c2ff..26b550654fb48 100644 --- a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-19.mdx +++ b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-19.mdx @@ -20,7 +20,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "inventoryService", - "type": "[IInventoryService](../interfaces/internal.IInventoryService.mdx)", + "type": "[IInventoryService](../../InventoryTypes/interfaces/internal.internal-1.InventoryTypes.IInventoryService.mdx)", "description": "", "optional": true, "defaultValue": "", diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-20.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-20.mdx index c947613008365..f991381eed465 100644 --- a/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-20.mdx +++ b/www/apps/docs/content/references/js-client/internal/types/internal.InjectedDependencies-20.mdx @@ -11,7 +11,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" `", + "description": "", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "parent_category", "type": "[ProductCategory](../classes/internal.ProductCategory.mdx) \\| `null`", diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobArgs.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobArgs.mdx new file mode 100644 index 0000000000000..86837d9c468e2 --- /dev/null +++ b/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobArgs.mdx @@ -0,0 +1,53 @@ +--- +displayed_sidebar: jsClientSidebar +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# ScheduledJobArgs + +### Type parameters + + + +### Type declaration + +`", + "description": "", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } +]} /> diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobConfig.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobConfig.mdx new file mode 100644 index 0000000000000..afafd46657aa6 --- /dev/null +++ b/www/apps/docs/content/references/js-client/internal/types/internal.internal.ScheduledJobConfig.mdx @@ -0,0 +1,53 @@ +--- +displayed_sidebar: jsClientSidebar +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# ScheduledJobConfig + +### Type parameters + + + +### Type declaration + + diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberArgs.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberArgs.mdx new file mode 100644 index 0000000000000..23da317c5af60 --- /dev/null +++ b/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberArgs.mdx @@ -0,0 +1,62 @@ +--- +displayed_sidebar: jsClientSidebar +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# SubscriberArgs + +### Type parameters + + + +### Type declaration + +`", + "description": "", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } +]} /> diff --git a/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberConfig.mdx b/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberConfig.mdx new file mode 100644 index 0000000000000..0ca7ad2a1fbf6 --- /dev/null +++ b/www/apps/docs/content/references/js-client/internal/types/internal.internal.SubscriberConfig.mdx @@ -0,0 +1,30 @@ +--- +displayed_sidebar: jsClientSidebar +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# SubscriberConfig + +### Type declaration + + diff --git a/www/apps/docs/content/references/js-client/modules/internal.mdx b/www/apps/docs/content/references/js-client/modules/internal.mdx index 3e1f0327fb865..72d969e1fb02b 100644 --- a/www/apps/docs/content/references/js-client/modules/internal.mdx +++ b/www/apps/docs/content/references/js-client/modules/internal.mdx @@ -449,12 +449,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [FilePropertyBag](../internal/interfaces/internal.FilePropertyBag.mdx) - [HTTPResponse](../internal/interfaces/internal.HTTPResponse.mdx) - [HeadersDefaults](../internal/interfaces/internal.HeadersDefaults.mdx) -- [ICacheService](../internal/interfaces/internal.ICacheService.mdx) -- [IEventBusModuleService](../internal/interfaces/internal.IEventBusModuleService.mdx) -- [IEventBusService](../internal/interfaces/internal.IEventBusService.mdx) -- [IInventoryService](../internal/interfaces/internal.IInventoryService.mdx) -- [IPricingModuleService](../internal/interfaces/internal.IPricingModuleService.mdx) -- [IStockLocationService](../internal/interfaces/internal.IStockLocationService.mdx) - [ITransactionBaseService](../internal/interfaces/internal.ITransactionBaseService.mdx) - [IncomingHttpHeaders](../internal/interfaces/internal.IncomingHttpHeaders.mdx) - [IpcSocketConnectOpts](../internal/interfaces/internal.IpcSocketConnectOpts.mdx) @@ -463,7 +457,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [Iterator](../internal/interfaces/internal.Iterator.mdx) - [IteratorReturnResult](../internal/interfaces/internal.IteratorReturnResult.mdx) - [IteratorYieldResult](../internal/interfaces/internal.IteratorYieldResult.mdx) -- [Logger](../internal/interfaces/internal.Logger.mdx) - [LookupAddress](../internal/interfaces/internal.LookupAddress.mdx) - [LookupAllOptions](../internal/interfaces/internal.LookupAllOptions.mdx) - [LookupOptions](../internal/interfaces/internal.LookupOptions.mdx) @@ -509,6 +502,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [StaticEventEmitterOptions](../internal/interfaces/internal.StaticEventEmitterOptions.mdx) - [StreamPipeOptions](../internal/interfaces/internal.StreamPipeOptions.mdx) - [StreamPipeOptions](../internal/interfaces/internal.StreamPipeOptions-1.mdx) +- [SubscriberContext](../internal/interfaces/internal.SubscriberContext.mdx) - [TcpSocketConnectOpts](../internal/interfaces/internal.TcpSocketConnectOpts.mdx) - [TransformOptions](../internal/interfaces/internal.TransformOptions.mdx) - [TransitionalOptions](../internal/interfaces/internal.TransitionalOptions.mdx) @@ -659,8 +653,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [CategoryQueryParams](../internal/types/internal.CategoryQueryParams.mdx) - [ClaimTypeValue](../internal/types/internal.ClaimTypeValue.mdx) - [ComposeFnParam](../internal/types/internal.ComposeFnParam.mdx) -- [ConfigModule](../internal/types/internal.ConfigModule.mdx) -- [Constructor](../internal/types/internal.Constructor.mdx) - [CreateAnalyticsConfig](../internal/types/internal.CreateAnalyticsConfig.mdx) - [CreateClaimInput](../internal/types/internal.CreateClaimInput.mdx) - [CreateClaimItemAdditionalItemInput](../internal/types/internal.CreateClaimItemAdditionalItemInput.mdx) @@ -717,7 +709,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [DiscountConditionInput](../internal/types/internal.DiscountConditionInput.mdx) - [DiscountConditionResourceType](../internal/types/internal.DiscountConditionResourceType.mdx) - [DraftOrderCreateProps](../internal/types/internal.DraftOrderCreateProps.mdx) -- [EmitData](../internal/types/internal.EmitData.mdx) - [EndingType](../internal/types/internal.EndingType.mdx) - [Exclude](../internal/types/internal.Exclude.mdx) - [ExpandScalar](../internal/types/internal.ExpandScalar.mdx) @@ -859,12 +850,10 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [ReadonlyPrimary](../internal/types/internal.ReadonlyPrimary.mdx) - [Record](../internal/types/internal.Record.mdx) - [RegionDetails](../internal/types/internal.RegionDetails.mdx) -- [RemoteQueryFunction](../internal/types/internal.RemoteQueryFunction.mdx) - [ReorderConditions](../internal/types/internal.ReorderConditions.mdx) - [RequestContext](../internal/types/internal.RequestContext.mdx) - [RequestMethod](../internal/types/internal.RequestMethod.mdx) - [ReservationItemDTO](../internal/types/internal.ReservationItemDTO.mdx) -- [ReserveQuantityContext](../internal/types/internal.ReserveQuantityContext.mdx) - [Response](../internal/types/internal.Response.mdx) - [ResponsePromise](../internal/types/internal.ResponsePromise.mdx) - [ResponseType](../internal/types/internal.ResponseType.mdx) @@ -915,8 +904,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [StoreSwapsRes](../internal/types/internal.StoreSwapsRes.mdx) - [StoreVariantsListRes](../internal/types/internal.StoreVariantsListRes.mdx) - [StoreVariantsRes](../internal/types/internal.StoreVariantsRes.mdx) -- [Subscriber](../internal/types/internal.Subscriber.mdx) -- [SubscriberContext](../internal/types/internal.SubscriberContext.mdx) - [SubtotalOptions](../internal/types/internal.SubtotalOptions.mdx) - [TaxLinesMaps](../internal/types/internal.TaxLinesMaps.mdx) - [TaxRateListByConfig](../internal/types/internal.TaxRateListByConfig.mdx) diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPriceListPrices.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPriceListPrices.mdx new file mode 100644 index 0000000000000..7397dd9750e5e --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPriceListPrices.mdx @@ -0,0 +1,315 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/addPriceListPrices +sidebar_label: addPriceListPrices +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# addPriceListPrices - Pricing Module Reference + +This documentation provides a reference to the `addPriceListPrices` method. This belongs to the Pricing Module. + +This method is used to add prices to price lists. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function addPriceListPrices (items: { + priceListId: string, + prices: { + currency_code: string, + amount: number, + price_set_id: string + }[] +}[]) { + const pricingService = await initializePricingModule() + + const priceLists = await pricingService.addPriceListPrices(items) + + // do something with the price lists or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPrices.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPrices.mdx index 5f7052612890f..4d7a705877b7c 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPrices.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addPrices.mdx @@ -22,7 +22,7 @@ This method adds prices to a price set. To add a default price to a price set, don't pass it any rules and make sure to pass it the `currency_code`: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -47,7 +47,7 @@ async function addPricesToPriceSet (priceSetId: string) { To add prices with rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -120,7 +120,7 @@ async function addPricesToPriceSet (priceSetId: string) { "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -154,7 +154,7 @@ async function addPricesToPriceSet (priceSetId: string) { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -163,7 +163,7 @@ async function addPricesToPriceSet (priceSetId: string) { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -194,7 +194,7 @@ async function addPricesToPriceSet (priceSetId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -221,7 +221,7 @@ async function addPricesToPriceSet (priceSetId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -280,10 +280,10 @@ async function addPricesToPriceSet (priceSetId: string) { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -321,6 +321,15 @@ async function addPricesToPriceSet (priceSetId: string) { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, @@ -383,7 +392,7 @@ This method adds prices to multiple price sets. To add a default price to a price set, don't pass it any rules and make sure to pass it the `currency_code`: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -408,7 +417,7 @@ async function addPricesToPriceSet (priceSetId: string) { To add prices with rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -481,7 +490,7 @@ async function addPricesToPriceSet (priceSetId: string) { "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -515,7 +524,7 @@ async function addPricesToPriceSet (priceSetId: string) { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -524,7 +533,7 @@ async function addPricesToPriceSet (priceSetId: string) { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -555,7 +564,7 @@ async function addPricesToPriceSet (priceSetId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -582,7 +591,7 @@ async function addPricesToPriceSet (priceSetId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addRules.mdx index 81e7ae4aecc8b..f040c77975089 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.addRules.mdx @@ -20,7 +20,7 @@ This method adds rules to a price set. ### Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -60,8 +60,8 @@ async function addRulesToPriceSet (priceSetId: string) { }, { "name": "rules", - "type": "`{ attribute: string }`[]", - "description": "The rules to add to a price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ attribute: string }``[]", + "description": "The rules to add to a price set.", "optional": false, "defaultValue": "", "expandable": false, @@ -69,7 +69,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "attribute", "type": "`string`", - "description": "", + "description": "The value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, @@ -90,7 +90,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -117,7 +117,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -176,10 +176,10 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -217,6 +217,15 @@ async function addRulesToPriceSet (priceSetId: string) { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, @@ -277,7 +286,7 @@ This method adds rules to multiple price sets. ### Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -317,8 +326,8 @@ async function addRulesToPriceSet (priceSetId: string) { }, { "name": "rules", - "type": "`{ attribute: string }`[]", - "description": "The rules to add to a price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ attribute: string }``[]", + "description": "The rules to add to a price set.", "optional": false, "defaultValue": "", "expandable": false, @@ -326,7 +335,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "attribute", "type": "`string`", - "description": "", + "description": "The value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, @@ -347,7 +356,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -374,7 +383,7 @@ async function addRulesToPriceSet (priceSetId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.calculatePrices.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.calculatePrices.mdx index 3b0cba20a5606..e774633f5a869 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.calculatePrices.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.calculatePrices.mdx @@ -20,7 +20,7 @@ This method is used to calculate prices based on the provided filters and contex When you calculate prices, you must at least specify the currency code: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" async function calculatePrice (priceSetId: string, currencyCode: string) { @@ -42,7 +42,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { To calculate prices for specific minimum and/or maximum quantity: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" async function calculatePrice (priceSetId: string, currencyCode: string) { @@ -65,7 +65,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { To calculate prices for custom rule types: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" async function calculatePrice (priceSetId: string, currencyCode: string) { @@ -137,7 +137,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -164,7 +164,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -196,7 +196,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { "children": [ { "name": "amount", - "type": "``null`` \\| `number`", + "type": "`null` \\| `string`", "description": "The calculated amount. It can possibly be `null` if there's no price set up for the provided context.", "optional": false, "defaultValue": "", @@ -205,7 +205,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { }, { "name": "currency_code", - "type": "``null`` \\| `string`", + "type": "`null` \\| `string`", "description": "The currency code of the calculated price. It can possibly be `null`.", "optional": false, "defaultValue": "", @@ -215,7 +215,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { { "name": "id", "type": "`string`", - "description": "The ID of the price set.", + "description": "The ID of the money amount.", "optional": false, "defaultValue": "", "expandable": false, @@ -223,7 +223,7 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `string`", "description": "The maximum quantity required to be purchased for this price to apply. It's set if the `quantity` property is provided in the context. Otherwise, its value will be `null`.", "optional": false, "defaultValue": "", @@ -232,12 +232,39 @@ async function calculatePrice (priceSetId: string, currencyCode: string) { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `string`", "description": "The minimum quantity required to be purchased for this price to apply. It's set if the `quantity` property is provided in the context. Otherwise, its value will be `null`.", "optional": false, "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_list_id", + "type": "`null` \\| `string`", + "description": "The ID of the associated price list, if any.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list_type", + "type": "`null` \\| `string`", + "description": "The type of the associated price list, if any.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] } ] } diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.create.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.create.mdx index e41ecc32d9d00..3c43342821146 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.create.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.create.mdx @@ -114,7 +114,7 @@ async function createPriceSet() { "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -148,7 +148,7 @@ async function createPriceSet() { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -157,7 +157,7 @@ async function createPriceSet() { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -177,8 +177,8 @@ async function createPriceSet() { }, { "name": "rules", - "type": "`{ rule_attribute: string }`[]", - "description": "The rules to associate with the price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ rule_attribute: string }``[]", + "description": "The rules to associate with the price set.", "optional": true, "defaultValue": "", "expandable": false, @@ -186,7 +186,7 @@ async function createPriceSet() { { "name": "rule_attribute", "type": "`string`", - "description": "", + "description": "the value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, @@ -207,7 +207,7 @@ async function createPriceSet() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -234,7 +234,7 @@ async function createPriceSet() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -293,10 +293,10 @@ async function createPriceSet() { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -334,6 +334,15 @@ async function createPriceSet() { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, @@ -485,7 +494,7 @@ async function createPriceSets() { "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -519,7 +528,7 @@ async function createPriceSets() { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -528,7 +537,7 @@ async function createPriceSets() { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -548,8 +557,8 @@ async function createPriceSets() { }, { "name": "rules", - "type": "`{ rule_attribute: string }`[]", - "description": "The rules to associate with the price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ rule_attribute: string }``[]", + "description": "The rules to associate with the price set.", "optional": true, "defaultValue": "", "expandable": false, @@ -557,7 +566,7 @@ async function createPriceSets() { { "name": "rule_attribute", "type": "`string`", - "description": "", + "description": "the value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, @@ -578,7 +587,7 @@ async function createPriceSets() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -605,7 +614,7 @@ async function createPriceSets() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createCurrencies.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createCurrencies.mdx index 615302c0be47e..e9213896197ed 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createCurrencies.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createCurrencies.mdx @@ -96,7 +96,7 @@ async function createCurrencies() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -123,7 +123,7 @@ async function createCurrencies() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createMoneyAmounts.mdx index 7d05a09766a07..99002c42366a4 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createMoneyAmounts.mdx @@ -55,7 +55,7 @@ async function retrieveMoneyAmounts() { "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -126,7 +126,7 @@ async function retrieveMoneyAmounts() { }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -135,7 +135,7 @@ async function retrieveMoneyAmounts() { }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -155,7 +155,7 @@ async function retrieveMoneyAmounts() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -182,7 +182,7 @@ async function retrieveMoneyAmounts() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -232,10 +232,10 @@ async function retrieveMoneyAmounts() { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -273,6 +273,15 @@ async function retrieveMoneyAmounts() { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] } diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceListRules.mdx new file mode 100644 index 0000000000000..ca5d29593c27b --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceListRules.mdx @@ -0,0 +1,211 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/createPriceListRules +sidebar_label: createPriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# createPriceListRules - Pricing Module Reference + +This documentation provides a reference to the `createPriceListRules` method. This belongs to the Pricing Module. + +This method is used to create price list rules. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function createPriceListRules (items: { + rule_type_id: string + price_list_id: string +}[]) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.createPriceListRules(items) + + // do something with the price list rule or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceLists.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceLists.mdx new file mode 100644 index 0000000000000..851fa1b80b84a --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceLists.mdx @@ -0,0 +1,414 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/createPriceLists +sidebar_label: createPriceLists +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# createPriceLists - Pricing Module Reference + +This documentation provides a reference to the `createPriceLists` method. This belongs to the Pricing Module. + +This method is used to create price lists. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function createPriceList (items: { + title: string + description: string + starts_at?: string + ends_at?: string +}[]) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.createPriceLists(items) + + // do something with the price lists or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceRules.mdx index 53381dbd30fa7..9848ced7305d0 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceRules.mdx @@ -18,16 +18,16 @@ This method is used to create new price rules based on the provided data. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" async function createPriceRules ( id: string, - priceSetId: string, - ruleTypeId: string, - value: string, - priceSetMoneyAmountId: string, + priceSetId: string, + ruleTypeId: string, + value: string, + priceSetMoneyAmountId: string, priceListId: string ) { const pricingService = await initializePricingModule() @@ -67,15 +67,6 @@ async function createPriceRules ( "expandable": false, "children": [] }, - { - "name": "price_list_id", - "type": "`string`", - "description": "The ID of the associated price list.", - "optional": false, - "defaultValue": "", - "expandable": false, - "children": [] - }, { "name": "price_set_id", "type": "`string`", @@ -88,7 +79,7 @@ async function createPriceRules ( { "name": "price_set_money_amount_id", "type": "`string`", - "description": "The ID of the associated price set money amount.", + "description": "", "optional": false, "defaultValue": "", "expandable": false, @@ -97,7 +88,7 @@ async function createPriceRules ( { "name": "priority", "type": "`number`", - "description": "The priority of the price rule in comparison to other applicable price rules.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, @@ -134,7 +125,7 @@ async function createPriceRules ( { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -161,7 +152,7 @@ async function createPriceRules ( { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -220,10 +211,10 @@ async function createPriceRules ( { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -256,10 +247,10 @@ async function createPriceRules ( { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceSetMoneyAmountRules.mdx index df304c3661120..f5fb93c14b9b7 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createPriceSetMoneyAmountRules.mdx @@ -19,7 +19,7 @@ a rule type. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -89,7 +89,7 @@ async function createPriceSetMoneyAmountRules (priceSetMoneyAmountId: string, ru { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -116,7 +116,7 @@ async function createPriceSetMoneyAmountRules (priceSetMoneyAmountId: string, ru { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -166,19 +166,19 @@ async function createPriceSetMoneyAmountRules (priceSetMoneyAmountId: string, ru { "name": "price_set_money_amount", "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", - "description": "The associated price set money amount. It may only be available if the relation `price_set_money_amount` is expanded.", + "description": "The associated price set money amount.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createRuleTypes.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createRuleTypes.mdx index 8c5cec522ffbd..d2cba36a6e721 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createRuleTypes.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.createRuleTypes.mdx @@ -94,7 +94,7 @@ async function createRuleTypes() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -121,7 +121,7 @@ async function createRuleTypes() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.delete.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.delete.mdx index 4ee8f16060e75..937b80e7a0416 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.delete.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.delete.mdx @@ -18,7 +18,7 @@ This method deletes price sets by their IDs. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -52,7 +52,7 @@ async function removePriceSetRule (priceSetIds: string[]) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -79,7 +79,7 @@ async function removePriceSetRule (priceSetIds: string[]) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteCurrencies.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteCurrencies.mdx index 8cea1e260c425..ab92bb9a371f3 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteCurrencies.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteCurrencies.mdx @@ -50,7 +50,7 @@ async function deleteCurrencies() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -77,7 +77,7 @@ async function deleteCurrencies() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteMoneyAmounts.mdx index 178aa1c4ed08b..afc8dc0baa13d 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteMoneyAmounts.mdx @@ -18,7 +18,7 @@ This method deletes money amounts by their IDs. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -54,7 +54,7 @@ async function deleteMoneyAmounts (moneyAmountIds: string[]) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -81,7 +81,7 @@ async function deleteMoneyAmounts (moneyAmountIds: string[]) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceListRules.mdx new file mode 100644 index 0000000000000..27670f942af3e --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceListRules.mdx @@ -0,0 +1,113 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/deletePriceListRules +sidebar_label: deletePriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# deletePriceListRules - Pricing Module Reference + +This documentation provides a reference to the `deletePriceListRules` method. This belongs to the Pricing Module. + +This method is used to delete price list rules. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function deletePriceListRules (priceListRuleIds: string[]) { + const pricingService = await initializePricingModule() + + await pricingService.deletePriceListRules(priceListRuleIds) +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceLists.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceLists.mdx new file mode 100644 index 0000000000000..79ea824399902 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceLists.mdx @@ -0,0 +1,113 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/deletePriceLists +sidebar_label: deletePriceLists +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# deletePriceLists - Pricing Module Reference + +This documentation provides a reference to the `deletePriceLists` method. This belongs to the Pricing Module. + +This method is used to delete price lists. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function deletePriceLists (ids: string[]) { + const pricingService = await initializePricingModule() + + await pricingService.deletePriceLists(ids) +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceRules.mdx index 7f8d3a72420a4..04d37364bf5b2 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceRules.mdx @@ -18,7 +18,7 @@ This method is used to delete price rules based on the specified IDs. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -54,7 +54,7 @@ async function deletePriceRules ( { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -81,7 +81,7 @@ async function deletePriceRules ( { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceSetMoneyAmountRules.mdx index 7dc61ee12b871..8cf73e39b300b 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deletePriceSetMoneyAmountRules.mdx @@ -18,7 +18,7 @@ This method is used to delete price set money amount rules based on the specifie ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -52,7 +52,7 @@ async function deletePriceSetMoneyAmountRule (id: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -79,7 +79,7 @@ async function deletePriceSetMoneyAmountRule (id: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteRuleTypes.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteRuleTypes.mdx index 7ad9169eb07e7..268b5d35027e0 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteRuleTypes.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.deleteRuleTypes.mdx @@ -18,7 +18,7 @@ This method is used to delete rule types based on the provided IDs. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -52,7 +52,7 @@ async function deleteRuleTypes (ruleTypeId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -79,7 +79,7 @@ async function deleteRuleTypes (ruleTypeId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.list.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.list.mdx index e583226e75689..d667b9af0ce43 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.list.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.list.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price sets based on optional To retrieve a list of price sets using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrievePriceSets (priceSetIds: string[]) { To specify relations that should be retrieved within the price sets: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrievePriceSets (priceSetIds: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -88,10 +88,10 @@ async function retrievePriceSets (priceSetIds: string[], skip: number, take: num You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" - + async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[], skip: number, take: number) { const pricingService = await initializePricingModule() @@ -290,7 +290,7 @@ async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[ { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -317,7 +317,7 @@ async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[ { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCount.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCount.mdx index a089d89daf283..cc6aa1cac6a33 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCount.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCount.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price sets along with the to To retrieve a list of prices sets using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrievePriceSets (priceSetIds: string[]) { To specify relations that should be retrieved within the price sets: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrievePriceSets (priceSetIds: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -88,10 +88,10 @@ async function retrievePriceSets (priceSetIds: string[], skip: number, take: num You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" - + async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[], skip: number, take: number) { const pricingService = await initializePricingModule() @@ -290,7 +290,7 @@ async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[ { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -317,7 +317,7 @@ async function retrievePriceSets (priceSetIds: string[], moneyAmountIds: string[ { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountCurrencies.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountCurrencies.mdx index bcb1e5535c320..c74b05d674cf6 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountCurrencies.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountCurrencies.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of currencies along with the to To retrieve a list of currencies using their codes: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveCurrencies (codes: string[]) { To specify attributes that should be retrieved within the money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrieveCurrencies (codes: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -210,7 +210,7 @@ async function retrieveCurrencies (codes: string[], skip: number, take: number) { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -237,7 +237,7 @@ async function retrieveCurrencies (codes: string[], skip: number, take: number) { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountMoneyAmounts.mdx index 34658f0b49a6f..87267398a78a3 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountMoneyAmounts.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of money amounts along with the To retrieve a list of money amounts using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[]) { To specify relations that should be retrieved within the money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -88,7 +88,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], skip: number, tak You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -251,7 +251,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -278,7 +278,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceListRules.mdx new file mode 100644 index 0000000000000..e304a3ea7f288 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceListRules.mdx @@ -0,0 +1,349 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/listAndCountPriceListRules +sidebar_label: listAndCountPriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# listAndCountPriceListRules - Pricing Module Reference + +This documentation provides a reference to the `listAndCountPriceListRules` method. This belongs to the Pricing Module. + +This method is used to retrieve a paginated list of price list ruless along with the total count of available price list ruless satisfying the provided filters. + +## Example + +To retrieve a list of price list vs using their IDs: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listAndCountPriceListRules (priceListRuleIds: string[]) { + const pricingService = await initializePricingModule() + + const [priceListRules, count] = await pricingService.listAndCountPriceListRules( + { + id: priceListRuleIds + }, + ) + + // do something with the price list rules or return them +} +``` + +To specify relations that should be retrieved within the price list rules: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listAndCountPriceListRules (priceListRuleIds: string[]) { + const pricingService = await initializePricingModule() + + const [priceListRules, count] = await pricingService.listAndCountPriceListRules( + { + id: priceListRuleIds + }, + { + relations: ["price_list_rule_values"] + } + ) + + // do something with the price list rules or return them +} +``` + +By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listAndCountPriceListRules (priceListRuleIds: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const [priceListRules, count] = await pricingService.listAndCountPriceListRules( + { + id: priceListRuleIds + }, + { + relations: ["price_list_rule_values"], + skip, + take + } + ) + + // do something with the price list rules or return them +} +``` + +You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listAndCountPriceListRules (priceListRuleIds: string[], ruleTypeIDs: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const [priceListRules, count] = await pricingService.listAndCountPriceListRules( + { + $and: [ + { + id: priceListRuleIds + }, + { + rule_types: ruleTypeIDs + } + ] + }, + { + relations: ["price_list_rule_values"], + skip, + take + } + ) + + // do something with the price list rules or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceLists.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceLists.mdx new file mode 100644 index 0000000000000..479ed13b43792 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceLists.mdx @@ -0,0 +1,377 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/listAndCountPriceLists +sidebar_label: listAndCountPriceLists +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# listAndCountPriceLists - Pricing Module Reference + +This documentation provides a reference to the `listAndCountPriceLists` method. This belongs to the Pricing Module. + +This method is used to retrieve a paginated list of price lists along with the total count of available price lists satisfying the provided filters. + +## Example + +To retrieve a list of price lists using their IDs: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceLists (priceListIds: string[]) { + const pricingService = await initializePricingModule() + + const [priceLists, count] = await pricingService.listPriceLists( + { + id: priceListIds + }, + ) + + // do something with the price lists or return them +} +``` + +To specify relations that should be retrieved within the price lists: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceLists (priceListIds: string[]) { + const pricingService = await initializePricingModule() + + const [priceLists, count] = await pricingService.listPriceLists( + { + id: priceListIds + }, + { + relations: ["price_set_money_amounts"] + } + ) + + // do something with the price lists or return them +} +``` + +By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceLists (priceListIds: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const [priceLists, count] = await pricingService.listPriceLists( + { + id: priceListIds + }, + { + relations: ["price_set_money_amounts"], + skip, + take + } + ) + + // do something with the price lists or return them +} +``` + +You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceLists (priceListIds: string[], titles: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const [priceLists, count] = await pricingService.listPriceLists( + { + $and: [ + { + id: priceListIds + }, + { + title: titles + } + ] + }, + { + relations: ["price_set_money_amounts"], + skip, + take + } + ) + + // do something with the price lists or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceRules.mdx index 0bc85eba85d68..cdac760bb11e1 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceRules.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price rules along with the t To retrieve a list of price rules using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrievePriceRules (id: string) { To specify relations that should be retrieved within the price rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -58,7 +58,7 @@ async function retrievePriceRules (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -80,7 +80,7 @@ async function retrievePriceRules (id: string, skip: number, take: number) { You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -258,7 +258,7 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -285,7 +285,7 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmountRules.mdx index c566a84bc67f7..c9d3b29f3089b 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmountRules.mdx @@ -13,7 +13,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" This documentation provides a reference to the `listAndCountPriceSetMoneyAmountRules` method. This belongs to the Pricing Module. -This method is used to retrieve a paginated list of price set money amount rules along with the total count of +This method is used to retrieve a paginated list of price set money amount rules along with the total count of available price set money amount rules satisfying the provided filters. ## Example @@ -21,7 +21,7 @@ available price set money amount rules satisfying the provided filters. To retrieve a list of price set money amounts using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -39,7 +39,7 @@ async function retrievePriceSetMoneyAmountRules (id: string) { To specify relations that should be retrieved within the price set money amount rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -59,7 +59,7 @@ async function retrievePriceSetMoneyAmountRules (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -81,7 +81,7 @@ async function retrievePriceSetMoneyAmountRules (id: string, skip: number, take: You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -259,7 +259,7 @@ async function retrievePriceSetMoneyAmountRules (ids: string[], ruleTypeId: stri { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -286,7 +286,7 @@ async function retrievePriceSetMoneyAmountRules (ids: string[], ruleTypeId: stri { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmounts.mdx index c662b58b0bf0f..cde4d7475e487 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmounts.mdx @@ -13,7 +13,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" This documentation provides a reference to the `listAndCountPriceSetMoneyAmounts` method. This belongs to the Pricing Module. -This method is used to retrieve a paginated list of price set money amounts along with the total count of +This method is used to retrieve a paginated list of price set money amounts along with the total count of available price set money amounts satisfying the provided filters. ## Example @@ -21,7 +21,7 @@ available price set money amounts satisfying the provided filters. To retrieve a list of price set money amounts using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -39,7 +39,7 @@ async function retrievePriceSetMoneyAmounts (id: string) { To specify relations that should be retrieved within the price set money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -59,7 +59,7 @@ async function retrievePriceSetMoneyAmounts (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -81,7 +81,7 @@ async function retrievePriceSetMoneyAmounts (id: string, skip: number, take: num You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -145,6 +145,15 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk "expandable": false, "children": [] }, + { + "name": "price_list_id", + "type": "`string`[]", + "description": "The IDs to filter the price set money amount's associated price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "price_set_id", "type": "`string`[]", @@ -241,7 +250,7 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -268,7 +277,7 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountRuleTypes.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountRuleTypes.mdx index 6f7e0a862513f..3bfc445d7b108 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountRuleTypes.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listAndCountRuleTypes.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of rule types along with the to To retrieve a list of rule types using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveRuleTypes (ruleTypeId: string) { To specify attributes that should be retrieved within the rule types: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -62,7 +62,7 @@ async function retrieveRuleTypes (ruleTypeId: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -86,7 +86,7 @@ async function retrieveRuleTypes (ruleTypeId: string, skip: number, take: number You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -255,7 +255,7 @@ async function retrieveRuleTypes (ruleTypeId: string[], name: string[], skip: nu { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -282,7 +282,7 @@ async function retrieveRuleTypes (ruleTypeId: string[], name: string[], skip: nu { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listCurrencies.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listCurrencies.mdx index c8cea5e729e62..732709cfdccee 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listCurrencies.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listCurrencies.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of currencies based on optional To retrieve a list of currencies using their codes: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveCurrencies (codes: string[]) { To specify attributes that should be retrieved within the money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrieveCurrencies (codes: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -210,7 +210,7 @@ async function retrieveCurrencies (codes: string[], skip: number, take: number) { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -237,7 +237,7 @@ async function retrieveCurrencies (codes: string[], skip: number, take: number) { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listMoneyAmounts.mdx index 562263721bdca..4381dbc7f0e13 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listMoneyAmounts.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of money amounts based on optio To retrieve a list of money amounts using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[]) { To specify relations that should be retrieved within the money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -63,7 +63,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[]) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -88,7 +88,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], skip: number, tak You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -251,7 +251,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -278,7 +278,7 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -328,10 +328,10 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -369,6 +369,15 @@ async function retrieveMoneyAmounts (moneyAmountIds: string[], currencyCode: str "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] } diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceListRules.mdx new file mode 100644 index 0000000000000..4be8642bd7f83 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceListRules.mdx @@ -0,0 +1,386 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/listPriceListRules +sidebar_label: listPriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# listPriceListRules - Pricing Module Reference + +This documentation provides a reference to the `listPriceListRules` method. This belongs to the Pricing Module. + +This method is used to retrieve a paginated list of price list rules based on optional filters and configuration. + +## Example + +To retrieve a list of price list vs using their IDs: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceListRules (priceListRuleIds: string[]) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.listPriceListRules( + { + id: priceListRuleIds + }, + ) + + // do something with the price list rules or return them +} +``` + +To specify relations that should be retrieved within the price list rules: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceListRules (priceListRuleIds: string[]) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.listPriceListRules( + { + id: priceListRuleIds + }, + { + relations: ["price_list_rule_values"] + } + ) + + // do something with the price list rules or return them +} +``` + +By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceListRules (priceListRuleIds: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.listPriceListRules( + { + id: priceListRuleIds + }, + { + relations: ["price_list_rule_values"], + skip, + take + } + ) + + // do something with the price list rules or return them +} +``` + +You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceListRules (priceListRuleIds: string[], ruleTypeIDs: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.listPriceListRules( + { + $and: [ + { + id: priceListRuleIds + }, + { + rule_types: ruleTypeIDs + } + ] + }, + { + relations: ["price_list_rule_values"], + skip, + take + } + ) + + // do something with the price list rules or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceLists.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceLists.mdx new file mode 100644 index 0000000000000..9b42a2e79a92c --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceLists.mdx @@ -0,0 +1,468 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/listPriceLists +sidebar_label: listPriceLists +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# listPriceLists - Pricing Module Reference + +This documentation provides a reference to the `listPriceLists` method. This belongs to the Pricing Module. + +This method is used to retrieve a paginated list of price lists based on optional filters and configuration. + +## Example + +To retrieve a list of price lists using their IDs: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceLists (priceListIds: string[]) { + const pricingService = await initializePricingModule() + + const priceLists = await pricingService.listPriceLists( + { + id: priceListIds + }, + ) + + // do something with the price lists or return them +} +``` + +To specify relations that should be retrieved within the price lists: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceLists (priceListIds: string[]) { + const pricingService = await initializePricingModule() + + const priceLists = await pricingService.listPriceLists( + { + id: priceListIds + }, + { + relations: ["price_set_money_amounts"] + } + ) + + // do something with the price lists or return them +} +``` + +By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceLists (priceListIds: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const priceLists = await pricingService.listPriceLists( + { + id: priceListIds + }, + { + relations: ["price_set_money_amounts"], + skip, + take + } + ) + + // do something with the price lists or return them +} +``` + +You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function listPriceLists (priceListIds: string[], titles: string[], skip: number, take: number) { + const pricingService = await initializePricingModule() + + const priceLists = await pricingService.listPriceLists( + { + $and: [ + { + id: priceListIds + }, + { + title: titles + } + ] + }, + { + relations: ["price_set_money_amounts"], + skip, + take + } + ) + + // do something with the price lists or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceRules.mdx index 4ab9e2a53388d..9c79f73316607 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceRules.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price rules based on optiona To retrieve a list of price rules using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrievePriceRules (id: string) { To specify relations that should be retrieved within the price rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -58,7 +58,7 @@ async function retrievePriceRules (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -80,7 +80,7 @@ async function retrievePriceRules (id: string, skip: number, take: number) { You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -258,7 +258,7 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -285,7 +285,7 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -344,10 +344,10 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -380,10 +380,10 @@ async function retrievePriceRules (ids: string[], name: string[], skip: number, { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmountRules.mdx index bd1d5969b9ec0..2c8554c19e28d 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmountRules.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price set money amount rules To retrieve a list of price set money amount rules using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrievePriceSetMoneyAmountRules (id: string) { To specify relations that should be retrieved within the price set money amount rules: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -58,7 +58,7 @@ async function retrievePriceSetMoneyAmountRules (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -80,7 +80,7 @@ async function retrievePriceSetMoneyAmountRules (id: string, skip: number, take: You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -258,7 +258,7 @@ async function retrievePriceSetMoneyAmountRules (ids: string[], ruleTypeId: stri { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -285,7 +285,7 @@ async function retrievePriceSetMoneyAmountRules (ids: string[], ruleTypeId: stri { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -335,19 +335,19 @@ async function retrievePriceSetMoneyAmountRules (ids: string[], ruleTypeId: stri { "name": "price_set_money_amount", "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", - "description": "The associated price set money amount. It may only be available if the relation `price_set_money_amount` is expanded.", + "description": "The associated price set money amount.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmounts.mdx index 166489f7ee71f..77d26cce233ed 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmounts.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of price set money amounts base To retrieve a list of price set money amounts using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrievePriceSetMoneyAmounts (id: string) { To specify relations that should be retrieved within the price set money amounts: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -58,7 +58,7 @@ async function retrievePriceSetMoneyAmounts (id: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -80,7 +80,7 @@ async function retrievePriceSetMoneyAmounts (id: string, skip: number, take: num You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -144,6 +144,15 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk "expandable": false, "children": [] }, + { + "name": "price_list_id", + "type": "`string`[]", + "description": "The IDs to filter the price set money amount's associated price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "price_set_id", "type": "`string`[]", @@ -240,7 +249,7 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -267,7 +276,7 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -317,34 +326,43 @@ async function retrievePriceSetMoneyAmounts (ids: string[], titles: string[], sk { "name": "money_amount", "type": "[MoneyAmountDTO](../../interfaces/MoneyAmountDTO.mdx)", - "description": "The money amount associated with the price set money amount. It may only be available if the relation `money_amount` is expanded.", + "description": "The money amount associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](../../interfaces/PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, "children": [] }, { "name": "price_rules", "type": "[PriceRuleDTO](../../interfaces/PriceRuleDTO.mdx)[]", - "description": "", + "description": "The price rules associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The price set associated with the price set money amount. It may only be available if the relation `price_set` is expanded.", + "description": "The price set associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "price_set_id", "type": "`string`", - "description": "", + "description": "The ID of the associated price set.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listRuleTypes.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listRuleTypes.mdx index 4810a723ef87f..355e0615fc94c 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listRuleTypes.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.listRuleTypes.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a paginated list of rule types based on optional To retrieve a list of rule types using their IDs: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -40,7 +40,7 @@ async function retrieveRuleTypes (ruleTypeId: string) { To specify attributes that should be retrieved within the rule types: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -62,7 +62,7 @@ async function retrieveRuleTypes (ruleTypeId: string) { By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -86,7 +86,7 @@ async function retrieveRuleTypes (ruleTypeId: string, skip: number, take: number You can also use the `$and` or `$or` properties of the `filter` parameter to use and/or conditions in your filters. For example: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -255,7 +255,7 @@ async function retrieveRuleTypes (ruleTypeId: string[], name: string[], skip: nu { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -282,7 +282,7 @@ async function retrieveRuleTypes (ruleTypeId: string[], name: string[], skip: nu { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removePriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removePriceListRules.mdx new file mode 100644 index 0000000000000..399da1567a9f2 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removePriceListRules.mdx @@ -0,0 +1,513 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/removePriceListRules +sidebar_label: removePriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# removePriceListRules - Pricing Module Reference + +This documentation provides a reference to the `removePriceListRules` method. This belongs to the Pricing Module. + +This method is used to remove rules from a price list. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function setPriceListRules (priceListId: string) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.removePriceListRules({ + priceListId, + rules: ["region_id"] + }) + + // do something with the price list or return it +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removeRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removeRules.mdx index 3ca9d6e5ec1dd..6bc1453ac73ab 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removeRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.removeRules.mdx @@ -18,7 +18,7 @@ This method remove rules from a price set. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -76,7 +76,7 @@ async function removePriceSetRule (priceSetId: string, ruleAttributes: []) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -103,7 +103,7 @@ async function removePriceSetRule (priceSetId: string, ruleAttributes: []) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieve.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieve.mdx index 898a686f765af..627a8fbda5dea 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieve.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieve.mdx @@ -13,14 +13,14 @@ import ParameterTypes from "@site/src/components/ParameterTypes" This documentation provides a reference to the `retrieve` method. This belongs to the Pricing Module. -This method is used to retrieves a price set by its ID. +This method is used to retrieve a price set by its ID. ## Example A simple example that retrieves a price set by its ID: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrievePriceSet (priceSetId: string) { To specify relations that should be retrieved: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -153,7 +153,7 @@ async function retrievePriceSet (priceSetId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -180,7 +180,7 @@ async function retrievePriceSet (priceSetId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -239,10 +239,10 @@ async function retrievePriceSet (priceSetId: string) { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -280,6 +280,15 @@ async function retrievePriceSet (priceSetId: string) { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveCurrency.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveCurrency.mdx index 7357f8153b595..9dfb2836f189c 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveCurrency.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveCurrency.mdx @@ -20,7 +20,7 @@ This method retrieves a currency by its code and and optionally based on the pro A simple example that retrieves a currency by its code: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrieveCurrency (code: string) { To specify attributes that should be retrieved: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -153,7 +153,7 @@ async function retrieveCurrency (code: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -180,7 +180,7 @@ async function retrieveCurrency (code: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveMoneyAmount.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveMoneyAmount.mdx index 38f28eee0770d..b573a9f93ed42 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveMoneyAmount.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveMoneyAmount.mdx @@ -20,7 +20,7 @@ This method retrieves a money amount by its ID. To retrieve a money amount by its ID: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -38,7 +38,7 @@ async function retrieveMoneyAmount (moneyAmountId: string) { To retrieve relations along with the money amount: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -153,7 +153,7 @@ async function retrieveMoneyAmount (moneyAmountId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -180,7 +180,7 @@ async function retrieveMoneyAmount (moneyAmountId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -222,10 +222,10 @@ async function retrieveMoneyAmount (moneyAmountId: string) { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "code", @@ -300,6 +300,79 @@ async function retrieveMoneyAmount (moneyAmountId: string) { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of a price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amount", + "type": "[MoneyAmountDTO](../../interfaces/MoneyAmountDTO.mdx)", + "description": "The money amount associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](../../interfaces/PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_rules", + "type": "[PriceRuleDTO](../../interfaces/PriceRuleDTO.mdx)[]", + "description": "The price rules associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", + "description": "The price set associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The title of the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] } ] } diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceList.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceList.mdx new file mode 100644 index 0000000000000..6e31cdb68adb3 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceList.mdx @@ -0,0 +1,590 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/retrievePriceList +sidebar_label: retrievePriceList +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# retrievePriceList - Pricing Module Reference + +This documentation provides a reference to the `retrievePriceList` method. This belongs to the Pricing Module. + +This method is used to retrieve a price list by its ID. + +## Example + +A simple example that retrieves a price list by its ID: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceList (priceListId: string) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.retrievePriceList( + priceListId + ) + + // do something with the price list or return it +} +``` + +To specify relations that should be retrieved: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceList (priceListId: string) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.retrievePriceList( + priceListId, + { + relations: ["price_set_money_amounts"] + } + ) + + // do something with the price list or return it +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceListRule.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceListRule.mdx new file mode 100644 index 0000000000000..5b34d3d53630d --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceListRule.mdx @@ -0,0 +1,425 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/retrievePriceListRule +sidebar_label: retrievePriceListRule +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# retrievePriceListRule - Pricing Module Reference + +This documentation provides a reference to the `retrievePriceListRule` method. This belongs to the Pricing Module. + +This method is used to retrieve a price list rule by its ID. + +## Example + +A simple example that retrieves a price list rule by its ID: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceListRule (priceListRuleId: string) { + const pricingService = await initializePricingModule() + + const priceListRule = await pricingService.retrievePriceListRule( + priceListRuleId + ) + + // do something with the price list rule or return it +} +``` + +To specify relations that should be retrieved: + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function retrievePriceListRule (priceListRuleId: string) { + const pricingService = await initializePricingModule() + + const priceListRule = await pricingService.retrievePriceListRule( + priceListRuleId, + { + relations: ["price_list"] + } + ) + + // do something with the price list rule or return it +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceRule.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceRule.mdx index a63746bb5b7d7..ca9e923a85f34 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceRule.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceRule.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a price rule by its ID. A simple example that retrieves a price rule by its ID: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -36,7 +36,7 @@ async function retrievePriceRule (id: string) { To specify relations that should be retrieved: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -148,7 +148,7 @@ async function retrievePriceRule (id: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -175,7 +175,7 @@ async function retrievePriceRule (id: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -226,10 +226,10 @@ async function retrievePriceRule (id: string) { { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -290,10 +290,10 @@ async function retrievePriceRule (id: string) { { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "default_priority", diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceSetMoneyAmountRules.mdx index 88f7bba861f19..831972d31f8e9 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrievePriceSetMoneyAmountRules.mdx @@ -20,7 +20,7 @@ This method is used to a price set money amount rule by its ID based on the prov A simple example that retrieves a price set money amount rule by its ID: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -36,7 +36,7 @@ async function retrievePriceSetMoneyAmountRule (id: string) { To specify relations that should be retrieved: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -148,7 +148,7 @@ async function retrievePriceSetMoneyAmountRule (id: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -175,7 +175,7 @@ async function retrievePriceSetMoneyAmountRule (id: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -217,10 +217,10 @@ async function retrievePriceSetMoneyAmountRule (id: string) { { "name": "price_set_money_amount", "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", - "description": "The associated price set money amount. It may only be available if the relation `price_set_money_amount` is expanded.", + "description": "The associated price set money amount.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -234,34 +234,43 @@ async function retrievePriceSetMoneyAmountRule (id: string) { { "name": "money_amount", "type": "[MoneyAmountDTO](../../interfaces/MoneyAmountDTO.mdx)", - "description": "The money amount associated with the price set money amount. It may only be available if the relation `money_amount` is expanded.", + "description": "The money amount associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](../../interfaces/PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, "children": [] }, { "name": "price_rules", "type": "[PriceRuleDTO](../../interfaces/PriceRuleDTO.mdx)[]", - "description": "", + "description": "The price rules associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The price set associated with the price set money amount. It may only be available if the relation `price_set` is expanded.", + "description": "The price set associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "price_set_id", "type": "`string`", - "description": "", + "description": "The ID of the associated price set.", "optional": true, "defaultValue": "", "expandable": false, @@ -281,10 +290,10 @@ async function retrievePriceSetMoneyAmountRule (id: string) { { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "default_priority", diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveRuleType.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveRuleType.mdx index ee4869e1a4fc0..68e975f585430 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveRuleType.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.retrieveRuleType.mdx @@ -20,7 +20,7 @@ This method is used to retrieve a rule type by its ID and and optionally based o A simple example that retrieves a rule type by its code: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -36,7 +36,7 @@ async function retrieveRuleType (ruleTypeId: string) { To specify attributes that should be retrieved: ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -148,7 +148,7 @@ async function retrieveRuleType (ruleTypeId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -175,7 +175,7 @@ async function retrieveRuleType (ruleTypeId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.setPriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.setPriceListRules.mdx new file mode 100644 index 0000000000000..3da757f2a9042 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.setPriceListRules.mdx @@ -0,0 +1,515 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/setPriceListRules +sidebar_label: setPriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# setPriceListRules - Pricing Module Reference + +This documentation provides a reference to the `setPriceListRules` method. This belongs to the Pricing Module. + +This method is used to set the rules of a price list. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function setPriceListRules (priceListId: string) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.setPriceListRules({ + priceListId, + rules: { + region_id: "US" + } + }) + + // do something with the price list or return it +} +``` + +## Parameters + +`", + "description": "The rules to add to the price list. Each key of the object is a rule type's `rule_attribute`, and its value is the value(s) of the rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "sharedContext", + "type": "[Context](../../interfaces/Context.mdx)", + "description": "A context used to share resources, such as transaction manager, between the application and the module.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [ + { + "name": "enableNestedTransactions", + "type": "`boolean`", + "description": "A boolean value indicating whether nested transactions are enabled.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "isolationLevel", + "type": "`string`", + "description": "A string indicating the isolation level of the context. Possible values are `READ UNCOMMITTED`, `READ COMMITTED`, `REPEATABLE READ`, or `SERIALIZABLE`.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "manager", + "type": "`TManager`", + "description": "An instance of a manager, typically an entity manager, of type `TManager`, which is a typed parameter passed to the context to specify the type of the `manager`.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "transactionId", + "type": "`string`", + "description": "A string indicating the ID of the current transaction.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "transactionManager", + "type": "`TManager`", + "description": "An instance of a transaction manager of type `TManager`, which is a typed parameter passed to the context to specify the type of the `transactionManager`.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + } +]} /> + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateCurrencies.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateCurrencies.mdx index f3fe8d9c0aeb8..4fdfeb17532d4 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateCurrencies.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateCurrencies.mdx @@ -94,7 +94,7 @@ async function updateCurrencies() { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -121,7 +121,7 @@ async function updateCurrencies() { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateMoneyAmounts.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateMoneyAmounts.mdx index 1a6c3aa143fef..3a3181f0a3a53 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateMoneyAmounts.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateMoneyAmounts.mdx @@ -18,7 +18,7 @@ This method updates existing money amounts. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -27,7 +27,7 @@ async function updateMoneyAmounts (moneyAmountId: string, amount: number) { const moneyAmounts = await pricingService.updateMoneyAmounts([ { - id: moneyAmountId, + id: moneyAmountId, amount } ]) @@ -105,7 +105,7 @@ async function updateMoneyAmounts (moneyAmountId: string, amount: number) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -132,7 +132,7 @@ async function updateMoneyAmounts (moneyAmountId: string, amount: number) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -182,10 +182,10 @@ async function updateMoneyAmounts (moneyAmountId: string, amount: number) { { "name": "currency", "type": "[CurrencyDTO](../../interfaces/CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -223,6 +223,15 @@ async function updateMoneyAmounts (moneyAmountId: string, amount: number) { "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] } diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceListRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceListRules.mdx new file mode 100644 index 0000000000000..ad2b8f5b31565 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceListRules.mdx @@ -0,0 +1,221 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/updatePriceListRules +sidebar_label: updatePriceListRules +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# updatePriceListRules - Pricing Module Reference + +This documentation provides a reference to the `updatePriceListRules` method. This belongs to the Pricing Module. + +This method is used to update price list rules. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function updatePriceListRules (items: { + id: string + rule_type_id?: string + price_list_id?: string +}[]) { + const pricingService = await initializePricingModule() + + const priceListRules = await pricingService.updatePriceListRules(items) + + // do something with the price list rule or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceLists.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceLists.mdx new file mode 100644 index 0000000000000..84076d9db9f04 --- /dev/null +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceLists.mdx @@ -0,0 +1,314 @@ +--- +displayed_sidebar: pricingReference +badge: + variant: orange + text: Beta +slug: /references/pricing/updatePriceLists +sidebar_label: updatePriceLists +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# updatePriceLists - Pricing Module Reference + +This documentation provides a reference to the `updatePriceLists` method. This belongs to the Pricing Module. + +This method is used to update price lists. + +## Example + +```ts +import { + initialize as initializePricingModule, +} from "@medusajs/pricing" + +async function updatePriceLists (items: { + id: string + title: string + description: string + starts_at?: string + ends_at?: string +}[]) { + const pricingService = await initializePricingModule() + + const priceList = await pricingService.updatePriceLists(items) + + // do something with the price lists or return them +} +``` + +## Parameters + + + +## Returns + + diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceRules.mdx index 1e5fefb3ee24b..c421a81789033 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceRules.mdx @@ -18,13 +18,13 @@ This method is used to update price rules, each with their provided data. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" async function updatePriceRules ( id: string, - priceSetId: string, + priceSetId: string, ) { const pricingService = await initializePricingModule() @@ -53,7 +53,7 @@ async function updatePriceRules ( { "name": "id", "type": "`string`", - "description": "The ID of the price rule to update.", + "description": "", "optional": false, "defaultValue": "", "expandable": false, @@ -71,7 +71,7 @@ async function updatePriceRules ( { "name": "price_set_id", "type": "`string`", - "description": "The ID of the associated price set.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, @@ -98,7 +98,7 @@ async function updatePriceRules ( { "name": "rule_type_id", "type": "`string`", - "description": "The ID of the associated rule type.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, @@ -126,7 +126,7 @@ async function updatePriceRules ( { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -153,7 +153,7 @@ async function updatePriceRules ( { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -212,10 +212,10 @@ async function updatePriceRules ( { "name": "price_set", "type": "[PriceSetDTO](../../interfaces/PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -248,10 +248,10 @@ async function updatePriceRules ( { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceSetMoneyAmountRules.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceSetMoneyAmountRules.mdx index 6f2e07dc8b84f..29f8f247e6044 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceSetMoneyAmountRules.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updatePriceSetMoneyAmountRules.mdx @@ -18,7 +18,7 @@ This method is used to update price set money amount rules, each with their prov ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -96,7 +96,7 @@ async function updatePriceSetMoneyAmountRules (id: string, value: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -123,7 +123,7 @@ async function updatePriceSetMoneyAmountRules (id: string, value: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, @@ -173,19 +173,19 @@ async function updatePriceSetMoneyAmountRules (id: string, value: string) { { "name": "price_set_money_amount", "type": "[PriceSetMoneyAmountDTO](../../interfaces/PriceSetMoneyAmountDTO.mdx)", - "description": "The associated price set money amount. It may only be available if the relation `price_set_money_amount` is expanded.", + "description": "The associated price set money amount.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { "name": "rule_type", "type": "[RuleTypeDTO](../../interfaces/RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { diff --git a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateRuleTypes.mdx b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateRuleTypes.mdx index a2a665fd61d08..22a02a2b7853b 100644 --- a/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateRuleTypes.mdx +++ b/www/apps/docs/content/references/pricing/IPricingModuleService/methods/IPricingModuleService.updateRuleTypes.mdx @@ -18,7 +18,7 @@ This method is used to update existing rule types with the provided data. ## Example ```ts -import { +import { initialize as initializePricingModule, } from "@medusajs/pricing" @@ -96,7 +96,7 @@ async function updateRuleTypes (ruleTypeId: string) { { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -123,7 +123,7 @@ async function updateRuleTypes (ruleTypeId: string) { { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/enums/PriceListStatus.mdx b/www/apps/docs/content/references/pricing/enums/PriceListStatus.mdx new file mode 100644 index 0000000000000..4114a7d4f60f3 --- /dev/null +++ b/www/apps/docs/content/references/pricing/enums/PriceListStatus.mdx @@ -0,0 +1,25 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListStatus + +The price list's status. + +## Enumeration Members + +### ACTIVE + + **ACTIVE** = `"active"` + +The price list is enabled and its prices can be used. + +___ + +### DRAFT + + **DRAFT** = `"draft"` + +The price list is disabled, meaning its prices can't be used yet. diff --git a/www/apps/docs/content/references/pricing/enums/PriceListType.mdx b/www/apps/docs/content/references/pricing/enums/PriceListType.mdx new file mode 100644 index 0000000000000..2f46797a8a795 --- /dev/null +++ b/www/apps/docs/content/references/pricing/enums/PriceListType.mdx @@ -0,0 +1,25 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListType + +The price list's type. + +## Enumeration Members + +### OVERRIDE + + **OVERRIDE** = `"override"` + +The price list's prices override original prices. This affects the calculated price of associated price sets. + +___ + +### SALE + + **SALE** = `"sale"` + +The price list's prices are used for a sale. diff --git a/www/apps/docs/content/references/pricing/index.md b/www/apps/docs/content/references/pricing/index.md index b26a8bdae3bce..e650998859a45 100644 --- a/www/apps/docs/content/references/pricing/index.md +++ b/www/apps/docs/content/references/pricing/index.md @@ -6,8 +6,14 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # Pricing Module Reference Reference +## Enumerations + +- [PriceListStatus](enums/PriceListStatus.mdx) +- [PriceListType](enums/PriceListType.mdx) + ## Interfaces +- [AddPriceListPricesDTO](interfaces/AddPriceListPricesDTO.mdx) - [AddPricesDTO](interfaces/AddPricesDTO.mdx) - [AddRulesDTO](interfaces/AddRulesDTO.mdx) - [BaseFilterable](interfaces/BaseFilterable.mdx) @@ -15,6 +21,9 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [Context](interfaces/Context.mdx) - [CreateCurrencyDTO](interfaces/CreateCurrencyDTO.mdx) - [CreateMoneyAmountDTO](interfaces/CreateMoneyAmountDTO.mdx) +- [CreatePriceListDTO](interfaces/CreatePriceListDTO.mdx) +- [CreatePriceListRuleDTO](interfaces/CreatePriceListRuleDTO.mdx) +- [CreatePriceListRules](interfaces/CreatePriceListRules.mdx) - [CreatePriceRuleDTO](interfaces/CreatePriceRuleDTO.mdx) - [CreatePriceSetDTO](interfaces/CreatePriceSetDTO.mdx) - [CreatePriceSetMoneyAmountRulesDTO](interfaces/CreatePriceSetMoneyAmountRulesDTO.mdx) @@ -23,6 +32,8 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [CurrencyDTO](interfaces/CurrencyDTO.mdx) - [FilterableCurrencyProps](interfaces/FilterableCurrencyProps.mdx) - [FilterableMoneyAmountProps](interfaces/FilterableMoneyAmountProps.mdx) +- [FilterablePriceListProps](interfaces/FilterablePriceListProps.mdx) +- [FilterablePriceListRuleProps](interfaces/FilterablePriceListRuleProps.mdx) - [FilterablePriceRuleProps](interfaces/FilterablePriceRuleProps.mdx) - [FilterablePriceSetMoneyAmountProps](interfaces/FilterablePriceSetMoneyAmountProps.mdx) - [FilterablePriceSetMoneyAmountRulesProps](interfaces/FilterablePriceSetMoneyAmountRulesProps.mdx) @@ -33,16 +44,24 @@ import ParameterTypes from "@site/src/components/ParameterTypes" - [JoinerServiceConfig](interfaces/JoinerServiceConfig.mdx) - [JoinerServiceConfigAlias](interfaces/JoinerServiceConfigAlias.mdx) - [MoneyAmountDTO](interfaces/MoneyAmountDTO.mdx) +- [PriceListDTO](interfaces/PriceListDTO.mdx) +- [PriceListPriceDTO](interfaces/PriceListPriceDTO.mdx) +- [PriceListRuleDTO](interfaces/PriceListRuleDTO.mdx) +- [PriceListRuleValueDTO](interfaces/PriceListRuleValueDTO.mdx) - [PriceRuleDTO](interfaces/PriceRuleDTO.mdx) - [PriceSetDTO](interfaces/PriceSetDTO.mdx) - [PriceSetMoneyAmountDTO](interfaces/PriceSetMoneyAmountDTO.mdx) - [PriceSetMoneyAmountRulesDTO](interfaces/PriceSetMoneyAmountRulesDTO.mdx) - [PricingContext](interfaces/PricingContext.mdx) - [PricingFilters](interfaces/PricingFilters.mdx) +- [RemovePriceListRulesDTO](interfaces/RemovePriceListRulesDTO.mdx) - [RemovePriceSetRulesDTO](interfaces/RemovePriceSetRulesDTO.mdx) - [RuleTypeDTO](interfaces/RuleTypeDTO.mdx) +- [SetPriceListRulesDTO](interfaces/SetPriceListRulesDTO.mdx) - [UpdateCurrencyDTO](interfaces/UpdateCurrencyDTO.mdx) - [UpdateMoneyAmountDTO](interfaces/UpdateMoneyAmountDTO.mdx) +- [UpdatePriceListDTO](interfaces/UpdatePriceListDTO.mdx) +- [UpdatePriceListRuleDTO](interfaces/UpdatePriceListRuleDTO.mdx) - [UpdatePriceRuleDTO](interfaces/UpdatePriceRuleDTO.mdx) - [UpdatePriceSetDTO](interfaces/UpdatePriceSetDTO.mdx) - [UpdatePriceSetMoneyAmountRulesDTO](interfaces/UpdatePriceSetMoneyAmountRulesDTO.mdx) diff --git a/www/apps/docs/content/references/pricing/interfaces/AddPriceListPricesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/AddPriceListPricesDTO.mdx new file mode 100644 index 0000000000000..abbc6a102e8f0 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/AddPriceListPricesDTO.mdx @@ -0,0 +1,133 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# AddPriceListPricesDTO + +The prices to be added to a price list. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/AddPricesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/AddPricesDTO.mdx index 12b13beac42e3..810e7834068f9 100644 --- a/www/apps/docs/content/references/pricing/interfaces/AddPricesDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/AddPricesDTO.mdx @@ -32,7 +32,7 @@ The prices to add to a price set. "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -103,7 +103,7 @@ The prices to add to a price set. }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -112,7 +112,7 @@ The prices to add to a price set. }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", diff --git a/www/apps/docs/content/references/pricing/interfaces/AddRulesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/AddRulesDTO.mdx index 87b76b8038a3c..3ca620c7b06a1 100644 --- a/www/apps/docs/content/references/pricing/interfaces/AddRulesDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/AddRulesDTO.mdx @@ -22,8 +22,8 @@ The rules to add to a price set. }, { "name": "rules", - "type": "`{ attribute: string }`[]", - "description": "The rules to add to a price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ attribute: string }``[]", + "description": "The rules to add to a price set.", "optional": false, "defaultValue": "", "expandable": false, @@ -31,7 +31,7 @@ The rules to add to a price set. { "name": "attribute", "type": "`string`", - "description": "", + "description": "The value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/interfaces/CalculatedPriceSetDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CalculatedPriceSetDTO.mdx index 12bbe7ccb2767..c9dd954d507a1 100644 --- a/www/apps/docs/content/references/pricing/interfaces/CalculatedPriceSetDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/CalculatedPriceSetDTO.mdx @@ -13,7 +13,7 @@ A calculated price set's data. diff --git a/www/apps/docs/content/references/pricing/interfaces/Context.mdx b/www/apps/docs/content/references/pricing/interfaces/Context.mdx index d117cd062ff94..9d1e2de19162d 100644 --- a/www/apps/docs/content/references/pricing/interfaces/Context.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/Context.mdx @@ -6,8 +6,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # Context -The interface tag is used to ensure that the type is documented similar to interfaces. - A shared context object that is used to share resources between the application and the module. ## Type parameters @@ -30,7 +28,7 @@ A shared context object that is used to share resources between the application { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -57,7 +55,7 @@ A shared context object that is used to share resources between the application { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/interfaces/CreateMoneyAmountDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreateMoneyAmountDTO.mdx index eb01ff66695f7..0157c8d9e9eda 100644 --- a/www/apps/docs/content/references/pricing/interfaces/CreateMoneyAmountDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/CreateMoneyAmountDTO.mdx @@ -15,7 +15,7 @@ The money amount to create. "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -86,7 +86,7 @@ The money amount to create. }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -95,7 +95,7 @@ The money amount to create. }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePriceListDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListDTO.mdx new file mode 100644 index 0000000000000..76248d4c0485a --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListDTO.mdx @@ -0,0 +1,234 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# CreatePriceListDTO + +The price list to create. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRuleDTO.mdx new file mode 100644 index 0000000000000..af665612989ba --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRuleDTO.mdx @@ -0,0 +1,50 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# CreatePriceListRuleDTO + +The price list rule to create. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRules.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRules.mdx new file mode 100644 index 0000000000000..3bf7d28d574c1 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePriceListRules.mdx @@ -0,0 +1,10 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# CreatePriceListRules + +The price list's rules to be set. Each key of the object is a rule type's `rule_attribute`, and its value + * is the values of the rule. diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePriceRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePriceRuleDTO.mdx index 5afea2d57b00c..fc4b183603bc2 100644 --- a/www/apps/docs/content/references/pricing/interfaces/CreatePriceRuleDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePriceRuleDTO.mdx @@ -20,15 +20,6 @@ A price rule to create. "expandable": false, "children": [] }, - { - "name": "price_list_id", - "type": "`string`", - "description": "The ID of the associated price list.", - "optional": false, - "defaultValue": "", - "expandable": false, - "children": [] - }, { "name": "price_set_id", "type": "`string`", @@ -41,7 +32,7 @@ A price rule to create. { "name": "price_set_money_amount_id", "type": "`string`", - "description": "The ID of the associated price set money amount.", + "description": "", "optional": false, "defaultValue": "", "expandable": false, @@ -50,7 +41,7 @@ A price rule to create. { "name": "priority", "type": "`number`", - "description": "The priority of the price rule in comparison to other applicable price rules.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePriceSetDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePriceSetDTO.mdx index 4d4222e37c2ab..4d56b368bc386 100644 --- a/www/apps/docs/content/references/pricing/interfaces/CreatePriceSetDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePriceSetDTO.mdx @@ -23,7 +23,7 @@ A price set to create. "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -94,7 +94,7 @@ A price set to create. }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -103,7 +103,7 @@ A price set to create. }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -123,8 +123,8 @@ A price set to create. }, { "name": "rules", - "type": "`{ rule_attribute: string }`[]", - "description": "The rules to associate with the price set. The value of `attribute` is the value of the rule's `rule_attribute` attribute.", + "type": "``{ rule_attribute: string }``[]", + "description": "The rules to associate with the price set.", "optional": true, "defaultValue": "", "expandable": false, @@ -132,7 +132,7 @@ A price set to create. { "name": "rule_attribute", "type": "`string`", - "description": "", + "description": "the value of the rule's `rule_attribute` attribute.", "optional": false, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/interfaces/CreatePricesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/CreatePricesDTO.mdx index 8f7ec0ec40ae9..aa981d9d9dc84 100644 --- a/www/apps/docs/content/references/pricing/interfaces/CreatePricesDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/CreatePricesDTO.mdx @@ -15,7 +15,7 @@ The prices to create part of a price set. "name": "amount", "type": "`number`", "description": "The amount of this money amount.", - "optional": true, + "optional": false, "defaultValue": "", "expandable": false, "children": [] @@ -86,7 +86,7 @@ The prices to create part of a price set. }, { "name": "max_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The maximum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", @@ -95,7 +95,7 @@ The prices to create part of a price set. }, { "name": "min_quantity", - "type": "``null`` \\| `number`", + "type": "`null` \\| `number`", "description": "The minimum quantity required to be purchased for this money amount to be applied.", "optional": true, "defaultValue": "", diff --git a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListProps.mdx b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListProps.mdx new file mode 100644 index 0000000000000..23742ade848f2 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListProps.mdx @@ -0,0 +1,98 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# FilterablePriceListProps + +#### Inteface + +Filters to apply on price lists. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListRuleProps.mdx b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListRuleProps.mdx new file mode 100644 index 0000000000000..cf35a02925b1e --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceListRuleProps.mdx @@ -0,0 +1,68 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# FilterablePriceListRuleProps + +Filters to apply on price list rules. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceRuleProps.mdx b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceRuleProps.mdx index 05f79d54c66de..5e084131e388a 100644 --- a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceRuleProps.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceRuleProps.mdx @@ -6,7 +6,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # FilterablePriceRuleProps -Filters to apply to price rules. +Filters to apply on price rules. ## Properties diff --git a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceSetMoneyAmountProps.mdx b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceSetMoneyAmountProps.mdx index 6fc4c1cc3cc78..0e53f9993ddef 100644 --- a/www/apps/docs/content/references/pricing/interfaces/FilterablePriceSetMoneyAmountProps.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/FilterablePriceSetMoneyAmountProps.mdx @@ -38,6 +38,15 @@ Filters to apply on price set money amounts. "expandable": false, "children": [] }, + { + "name": "price_list_id", + "type": "`string`[]", + "description": "The IDs to filter the price set money amount's associated price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "price_set_id", "type": "`string`[]", diff --git a/www/apps/docs/content/references/pricing/interfaces/IPricingModuleService.mdx b/www/apps/docs/content/references/pricing/interfaces/IPricingModuleService.mdx index 5e92b653f2514..3c562baa7f461 100644 --- a/www/apps/docs/content/references/pricing/interfaces/IPricingModuleService.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/IPricingModuleService.mdx @@ -14,18 +14,23 @@ This section of the documentation provides a reference to the `IPricingModuleSer ## Methods +- [addPriceListPrices](../IPricingModuleService/methods/IPricingModuleService.addPriceListPrices.mdx) - [addPrices](../IPricingModuleService/methods/IPricingModuleService.addPrices.mdx) - [addRules](../IPricingModuleService/methods/IPricingModuleService.addRules.mdx) - [calculatePrices](../IPricingModuleService/methods/IPricingModuleService.calculatePrices.mdx) - [create](../IPricingModuleService/methods/IPricingModuleService.create.mdx) - [createCurrencies](../IPricingModuleService/methods/IPricingModuleService.createCurrencies.mdx) - [createMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.createMoneyAmounts.mdx) +- [createPriceListRules](../IPricingModuleService/methods/IPricingModuleService.createPriceListRules.mdx) +- [createPriceLists](../IPricingModuleService/methods/IPricingModuleService.createPriceLists.mdx) - [createPriceRules](../IPricingModuleService/methods/IPricingModuleService.createPriceRules.mdx) - [createPriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.createPriceSetMoneyAmountRules.mdx) - [createRuleTypes](../IPricingModuleService/methods/IPricingModuleService.createRuleTypes.mdx) - [delete](../IPricingModuleService/methods/IPricingModuleService.delete.mdx) - [deleteCurrencies](../IPricingModuleService/methods/IPricingModuleService.deleteCurrencies.mdx) - [deleteMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.deleteMoneyAmounts.mdx) +- [deletePriceListRules](../IPricingModuleService/methods/IPricingModuleService.deletePriceListRules.mdx) +- [deletePriceLists](../IPricingModuleService/methods/IPricingModuleService.deletePriceLists.mdx) - [deletePriceRules](../IPricingModuleService/methods/IPricingModuleService.deletePriceRules.mdx) - [deletePriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.deletePriceSetMoneyAmountRules.mdx) - [deleteRuleTypes](../IPricingModuleService/methods/IPricingModuleService.deleteRuleTypes.mdx) @@ -33,25 +38,35 @@ This section of the documentation provides a reference to the `IPricingModuleSer - [listAndCount](../IPricingModuleService/methods/IPricingModuleService.listAndCount.mdx) - [listAndCountCurrencies](../IPricingModuleService/methods/IPricingModuleService.listAndCountCurrencies.mdx) - [listAndCountMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.listAndCountMoneyAmounts.mdx) +- [listAndCountPriceListRules](../IPricingModuleService/methods/IPricingModuleService.listAndCountPriceListRules.mdx) +- [listAndCountPriceLists](../IPricingModuleService/methods/IPricingModuleService.listAndCountPriceLists.mdx) - [listAndCountPriceRules](../IPricingModuleService/methods/IPricingModuleService.listAndCountPriceRules.mdx) - [listAndCountPriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmountRules.mdx) - [listAndCountPriceSetMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.listAndCountPriceSetMoneyAmounts.mdx) - [listAndCountRuleTypes](../IPricingModuleService/methods/IPricingModuleService.listAndCountRuleTypes.mdx) - [listCurrencies](../IPricingModuleService/methods/IPricingModuleService.listCurrencies.mdx) - [listMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.listMoneyAmounts.mdx) +- [listPriceListRules](../IPricingModuleService/methods/IPricingModuleService.listPriceListRules.mdx) +- [listPriceLists](../IPricingModuleService/methods/IPricingModuleService.listPriceLists.mdx) - [listPriceRules](../IPricingModuleService/methods/IPricingModuleService.listPriceRules.mdx) - [listPriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmountRules.mdx) - [listPriceSetMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.listPriceSetMoneyAmounts.mdx) - [listRuleTypes](../IPricingModuleService/methods/IPricingModuleService.listRuleTypes.mdx) +- [removePriceListRules](../IPricingModuleService/methods/IPricingModuleService.removePriceListRules.mdx) - [removeRules](../IPricingModuleService/methods/IPricingModuleService.removeRules.mdx) - [retrieve](../IPricingModuleService/methods/IPricingModuleService.retrieve.mdx) - [retrieveCurrency](../IPricingModuleService/methods/IPricingModuleService.retrieveCurrency.mdx) - [retrieveMoneyAmount](../IPricingModuleService/methods/IPricingModuleService.retrieveMoneyAmount.mdx) +- [retrievePriceList](../IPricingModuleService/methods/IPricingModuleService.retrievePriceList.mdx) +- [retrievePriceListRule](../IPricingModuleService/methods/IPricingModuleService.retrievePriceListRule.mdx) - [retrievePriceRule](../IPricingModuleService/methods/IPricingModuleService.retrievePriceRule.mdx) - [retrievePriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.retrievePriceSetMoneyAmountRules.mdx) - [retrieveRuleType](../IPricingModuleService/methods/IPricingModuleService.retrieveRuleType.mdx) +- [setPriceListRules](../IPricingModuleService/methods/IPricingModuleService.setPriceListRules.mdx) - [updateCurrencies](../IPricingModuleService/methods/IPricingModuleService.updateCurrencies.mdx) - [updateMoneyAmounts](../IPricingModuleService/methods/IPricingModuleService.updateMoneyAmounts.mdx) +- [updatePriceListRules](../IPricingModuleService/methods/IPricingModuleService.updatePriceListRules.mdx) +- [updatePriceLists](../IPricingModuleService/methods/IPricingModuleService.updatePriceLists.mdx) - [updatePriceRules](../IPricingModuleService/methods/IPricingModuleService.updatePriceRules.mdx) - [updatePriceSetMoneyAmountRules](../IPricingModuleService/methods/IPricingModuleService.updatePriceSetMoneyAmountRules.mdx) - [updateRuleTypes](../IPricingModuleService/methods/IPricingModuleService.updateRuleTypes.mdx) diff --git a/www/apps/docs/content/references/pricing/interfaces/JoinerServiceConfig.mdx b/www/apps/docs/content/references/pricing/interfaces/JoinerServiceConfig.mdx index ffcf9f40925d7..1d6ef6477c7d4 100644 --- a/www/apps/docs/content/references/pricing/interfaces/JoinerServiceConfig.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/JoinerServiceConfig.mdx @@ -29,7 +29,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" }, { "name": "extends", - "type": "`{ relationship: [JoinerRelationship](../types/JoinerRelationship.mdx) ; serviceName: string }`[]", + "type": "``{ relationship: [JoinerRelationship](../types/JoinerRelationship.mdx) ; serviceName: string }``[]", "description": "", "optional": true, "defaultValue": "", diff --git a/www/apps/docs/content/references/pricing/interfaces/MoneyAmountDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/MoneyAmountDTO.mdx index bdb42834fa0ed..a4266fb7a6c9d 100644 --- a/www/apps/docs/content/references/pricing/interfaces/MoneyAmountDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/MoneyAmountDTO.mdx @@ -23,10 +23,10 @@ A money amount's data. A money amount represents a price. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "code", @@ -101,5 +101,352 @@ A money amount's data. A money amount represents a price. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of a price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amount", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", + "description": "The money amount associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "amount", + "type": "`number`", + "description": "The price of this money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "currency", + "type": "[CurrencyDTO](CurrencyDTO.mdx)", + "description": "The money amount's currency.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "currency_code", + "type": "`string`", + "description": "The currency code of this money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The ID of the money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "max_quantity", + "type": "`number`", + "description": "The maximum quantity required to be purchased for this price to be applied.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "min_quantity", + "type": "`number`", + "description": "The minimum quantity required to be purchased for this price to be applied.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + } + ] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "ends_at", + "type": "`null` \\| `string`", + "description": "The price list expires after this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The price list's ID.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amounts", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)[]", + "description": "The associated money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "number_rules", + "type": "`number`", + "description": "The number of rules associated with this price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list_rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_money_amounts", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)[]", + "description": "The associated price set money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rule_types", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)[]", + "description": "The associated rule types.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "starts_at", + "type": "`null` \\| `string`", + "description": "The price list is enabled starting from this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "status", + "type": "[PriceListStatus](../enums/PriceListStatus.mdx)", + "description": "The price list's status.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The price list's title.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "price_rules", + "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", + "description": "The price rules associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of the price rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list_id", + "type": "`string`", + "description": "The ID of the associated price list.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](PriceSetDTO.mdx)", + "description": "The associated price set.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_set_money_amount_id", + "type": "`string`", + "description": "The ID of the associated price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "priority", + "type": "`number`", + "description": "The priority of the price rule in comparison to other applicable price rules.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "rule_type", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", + "description": "The associated rule type.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rule_type_id", + "type": "`string`", + "description": "The ID of the associated rule type.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "value", + "type": "`string`", + "description": "The value of the price rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](PriceSetDTO.mdx)", + "description": "The price set associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of the price set.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amounts", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)[]", + "description": "The prices that belong to this price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "rule_types", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)[]", + "description": "The rule types applied on this price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The title of the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] } ]} /> diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceListDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceListDTO.mdx new file mode 100644 index 0000000000000..77b4938ac11d7 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/PriceListDTO.mdx @@ -0,0 +1,1094 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListDTO + +A price list's details. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceListPriceDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceListPriceDTO.mdx new file mode 100644 index 0000000000000..eba5be0250b98 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/PriceListPriceDTO.mdx @@ -0,0 +1,114 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListPriceDTO + +The prices associated with a price list. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceListRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceListRuleDTO.mdx new file mode 100644 index 0000000000000..b5fa0c7508581 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/PriceListRuleDTO.mdx @@ -0,0 +1,546 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListRuleDTO + +The price list rule's details. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceListRuleValueDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceListRuleValueDTO.mdx new file mode 100644 index 0000000000000..24d42e59329d5 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/PriceListRuleValueDTO.mdx @@ -0,0 +1,252 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# PriceListRuleValueDTO + +The price list rule value's details. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceRuleDTO.mdx index 9c8196eabf19c..303cbf68b8711 100644 --- a/www/apps/docs/content/references/pricing/interfaces/PriceRuleDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/PriceRuleDTO.mdx @@ -32,10 +32,10 @@ A price rule's data. { "name": "price_set", "type": "[PriceSetDTO](PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -66,10 +66,10 @@ A price rule's data. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -107,6 +107,15 @@ A price rule's data. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, @@ -188,10 +197,10 @@ A price rule's data. { "name": "rule_type", "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "default_priority", diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceSetDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceSetDTO.mdx index e6736baf92e6e..f3aba2f4f7eae 100644 --- a/www/apps/docs/content/references/pricing/interfaces/PriceSetDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/PriceSetDTO.mdx @@ -40,10 +40,10 @@ A price set's data. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "code", @@ -118,6 +118,79 @@ A price set's data. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of a price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amount", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", + "description": "The money amount associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_rules", + "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", + "description": "The price rules associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](PriceSetDTO.mdx)", + "description": "The price set associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The title of the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] } ] }, diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountDTO.mdx index 2729e26e40651..9a1727e76f5d4 100644 --- a/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountDTO.mdx @@ -23,10 +23,10 @@ A price set money amount's data. { "name": "money_amount", "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", - "description": "The money amount associated with the price set money amount. It may only be available if the relation `money_amount` is expanded.", + "description": "The money amount associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "amount", @@ -40,10 +40,10 @@ A price set money amount's data. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "code", @@ -118,16 +118,474 @@ A price set money amount's data. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of a price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amount", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", + "description": "The money amount associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_rules", + "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", + "description": "The price rules associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](PriceSetDTO.mdx)", + "description": "The price set associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The title of the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + } + ] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "ends_at", + "type": "`null` \\| `string`", + "description": "The price list expires after this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The price list's ID.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amounts", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)[]", + "description": "The associated money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "amount", + "type": "`number`", + "description": "The price of this money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "currency", + "type": "[CurrencyDTO](CurrencyDTO.mdx)", + "description": "The money amount's currency.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "currency_code", + "type": "`string`", + "description": "The currency code of this money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The ID of the money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "max_quantity", + "type": "`number`", + "description": "The maximum quantity required to be purchased for this price to be applied.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "min_quantity", + "type": "`number`", + "description": "The minimum quantity required to be purchased for this price to be applied.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + } + ] + }, + { + "name": "number_rules", + "type": "`number`", + "description": "The number of rules associated with this price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list_rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The price list rule's ID.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The associated price list.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list_rule_values", + "type": "[PriceListRuleValueDTO](PriceListRuleValueDTO.mdx)[]", + "description": "The associated rule values.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rule_type", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", + "description": "The associated rule type.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "value", + "type": "`string`", + "description": "The value of the rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "price_set_money_amounts", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)[]", + "description": "The associated price set money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The ID of a price set money amount.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amount", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", + "description": "The money amount associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_rules", + "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", + "description": "The price rules associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set", + "type": "[PriceSetDTO](PriceSetDTO.mdx)", + "description": "The price set associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_id", + "type": "`string`", + "description": "The ID of the associated price set.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The title of the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "rule_types", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)[]", + "description": "The associated rule types.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "default_priority", + "type": "`number`", + "description": "The priority of the rule type. This is useful when calculating the price of a price set, and multiple rules satisfy the provided context. The higher the value, the higher the priority of the rule type.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The ID of the rule type.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "name", + "type": "`string`", + "description": "The display name of the rule type.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "rule_attribute", + "type": "`string`", + "description": "The unique name used to later identify the rule\\_attribute. For example, it can be used in the `context` parameter of the `calculatePrices` method to specify a rule for calculating the price.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "id", + "type": "`string`", + "description": "The price list rule's ID.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The associated price list.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_list_rule_values", + "type": "[PriceListRuleValueDTO](PriceListRuleValueDTO.mdx)[]", + "description": "The associated rule values.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rule_type", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", + "description": "The associated rule type.", + "optional": false, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "value", + "type": "`string`", + "description": "The value of the rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "starts_at", + "type": "`null` \\| `string`", + "description": "The price list is enabled starting from this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "status", + "type": "[PriceListStatus](../enums/PriceListStatus.mdx)", + "description": "The price list's status.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [ + { + "name": "ACTIVE", + "type": "`\"active\"`", + "description": "The price list is enabled and its prices can be used.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "DRAFT", + "type": "`\"draft\"`", + "description": "The price list is disabled, meaning its prices can't be used yet.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + } + ] + }, + { + "name": "title", + "type": "`string`", + "description": "The price list's title.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] } ] }, { "name": "price_rules", "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", - "description": "", + "description": "The price rules associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -150,10 +608,10 @@ A price set money amount's data. { "name": "price_set", "type": "[PriceSetDTO](PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -214,10 +672,10 @@ A price set money amount's data. { "name": "rule_type", "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "default_priority", @@ -280,10 +738,10 @@ A price set money amount's data. { "name": "price_set", "type": "[PriceSetDTO](PriceSetDTO.mdx)", - "description": "The price set associated with the price set money amount. It may only be available if the relation `price_set` is expanded.", + "description": "The price set associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -314,10 +772,10 @@ A price set money amount's data. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -355,6 +813,15 @@ A price set money amount's data. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] } ] }, @@ -409,7 +876,7 @@ A price set money amount's data. { "name": "price_set_id", "type": "`string`", - "description": "", + "description": "The ID of the associated price set.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountRulesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountRulesDTO.mdx index 0ff5ffea8f2b6..2b6b3b9d61b9c 100644 --- a/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountRulesDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/PriceSetMoneyAmountRulesDTO.mdx @@ -23,10 +23,10 @@ A price set money amount rule's data. { "name": "price_set_money_amount", "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", - "description": "The associated price set money amount. It may only be available if the relation `price_set_money_amount` is expanded.", + "description": "The associated price set money amount.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -40,10 +40,10 @@ A price set money amount rule's data. { "name": "money_amount", "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)", - "description": "The money amount associated with the price set money amount. It may only be available if the relation `money_amount` is expanded.", + "description": "The money amount associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "amount", @@ -57,10 +57,10 @@ A price set money amount rule's data. { "name": "currency", "type": "[CurrencyDTO](CurrencyDTO.mdx)", - "description": "The money amount's currency. Since this is a relation, it will only be retrieved if it's passed to the `relations` array of the find-configuration options.", + "description": "The money amount's currency.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -98,16 +98,134 @@ A price set money amount rule's data. "defaultValue": "", "expandable": false, "children": [] + }, + { + "name": "price_set_money_amount", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)", + "description": "The details of the relation between the money amount and its associated price set.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + } + ] + }, + { + "name": "price_list", + "type": "[PriceListDTO](PriceListDTO.mdx)", + "description": "The price list associated with the price set money amount.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [ + { + "name": "ends_at", + "type": "`null` \\| `string`", + "description": "The price list expires after this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "id", + "type": "`string`", + "description": "The price list's ID.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "money_amounts", + "type": "[MoneyAmountDTO](MoneyAmountDTO.mdx)[]", + "description": "The associated money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "number_rules", + "type": "`number`", + "description": "The number of rules associated with this price list.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "price_list_rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "price_set_money_amounts", + "type": "[PriceSetMoneyAmountDTO](PriceSetMoneyAmountDTO.mdx)[]", + "description": "The associated price set money amounts.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rule_types", + "type": "[RuleTypeDTO](RuleTypeDTO.mdx)[]", + "description": "The associated rule types.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "rules", + "type": "[PriceListRuleDTO](PriceListRuleDTO.mdx)[]", + "description": "The price set's rules.", + "optional": true, + "defaultValue": "", + "expandable": true, + "children": [] + }, + { + "name": "starts_at", + "type": "`null` \\| `string`", + "description": "The price list is enabled starting from this date.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "status", + "type": "[PriceListStatus](../enums/PriceListStatus.mdx)", + "description": "The price list's status.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, + { + "name": "title", + "type": "`string`", + "description": "The price list's title.", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] } ] }, { "name": "price_rules", "type": "[PriceRuleDTO](PriceRuleDTO.mdx)[]", - "description": "", + "description": "The price rules associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -130,10 +248,10 @@ A price set money amount rule's data. { "name": "price_set", "type": "[PriceSetDTO](PriceSetDTO.mdx)", - "description": "The associated price set. It may only be available if the relation `price_set` is expanded.", + "description": "The associated price set.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -166,10 +284,10 @@ A price set money amount rule's data. { "name": "rule_type", "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] }, { @@ -195,10 +313,10 @@ A price set money amount rule's data. { "name": "price_set", "type": "[PriceSetDTO](PriceSetDTO.mdx)", - "description": "The price set associated with the price set money amount. It may only be available if the relation `price_set` is expanded.", + "description": "The price set associated with the price set money amount.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "id", @@ -232,7 +350,7 @@ A price set money amount rule's data. { "name": "price_set_id", "type": "`string`", - "description": "", + "description": "The ID of the associated price set.", "optional": true, "defaultValue": "", "expandable": false, @@ -252,10 +370,10 @@ A price set money amount rule's data. { "name": "rule_type", "type": "[RuleTypeDTO](RuleTypeDTO.mdx)", - "description": "The associated rule type. It may only be available if the relation `rule_type` is expanded.", + "description": "The associated rule type.", "optional": false, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [ { "name": "default_priority", diff --git a/www/apps/docs/content/references/pricing/interfaces/RemovePriceListRulesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/RemovePriceListRulesDTO.mdx new file mode 100644 index 0000000000000..03543e5717b63 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/RemovePriceListRulesDTO.mdx @@ -0,0 +1,32 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# RemovePriceListRulesDTO + +The rules to remove from a price list. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/SetPriceListRulesDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/SetPriceListRulesDTO.mdx new file mode 100644 index 0000000000000..7ed9260d25330 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/SetPriceListRulesDTO.mdx @@ -0,0 +1,32 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# SetPriceListRulesDTO + +The rules to add to a price list. + +## Properties + +`", + "description": "The rules to add to the price list. Each key of the object is a rule type's `rule_attribute`, and its value is the value(s) of the rule.", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + } +]} /> diff --git a/www/apps/docs/content/references/pricing/interfaces/UpdateMoneyAmountDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/UpdateMoneyAmountDTO.mdx index 76e0c481aae3c..19aad4943c094 100644 --- a/www/apps/docs/content/references/pricing/interfaces/UpdateMoneyAmountDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/UpdateMoneyAmountDTO.mdx @@ -6,8 +6,6 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # UpdateMoneyAmountDTO -* - The data to update in a money amount. The `id` is used to identify which money amount to update. ## Properties diff --git a/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListDTO.mdx new file mode 100644 index 0000000000000..fdecc4743d859 --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListDTO.mdx @@ -0,0 +1,96 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# UpdatePriceListDTO + +The attributes to update in a price list. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListRuleDTO.mdx new file mode 100644 index 0000000000000..85784efc002bd --- /dev/null +++ b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceListRuleDTO.mdx @@ -0,0 +1,59 @@ +--- +displayed_sidebar: pricingReference +--- + +import ParameterTypes from "@site/src/components/ParameterTypes" + +# UpdatePriceListRuleDTO + +The attributes to update in a price list rule. + +## Properties + + diff --git a/www/apps/docs/content/references/pricing/interfaces/UpdatePriceRuleDTO.mdx b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceRuleDTO.mdx index 37b8c3901c3c4..3567e6a5a9b88 100644 --- a/www/apps/docs/content/references/pricing/interfaces/UpdatePriceRuleDTO.mdx +++ b/www/apps/docs/content/references/pricing/interfaces/UpdatePriceRuleDTO.mdx @@ -14,7 +14,7 @@ The data to update in a price rule. The `id` is used to identify which money amo { "name": "id", "type": "`string`", - "description": "The ID of the price rule to update.", + "description": "", "optional": false, "defaultValue": "", "expandable": false, @@ -32,7 +32,7 @@ The data to update in a price rule. The `id` is used to identify which money amo { "name": "price_set_id", "type": "`string`", - "description": "The ID of the associated price set.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, @@ -59,7 +59,7 @@ The data to update in a price rule. The `id` is used to identify which money amo { "name": "rule_type_id", "type": "`string`", - "description": "The ID of the associated rule type.", + "description": "", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/pricing/types/Exclude.mdx b/www/apps/docs/content/references/pricing/types/Exclude.mdx index d62dafce19d9a..df5ea42dd2e01 100644 --- a/www/apps/docs/content/references/pricing/types/Exclude.mdx +++ b/www/apps/docs/content/references/pricing/types/Exclude.mdx @@ -6,7 +6,7 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # Exclude - **Exclude**``: T extends U ? never : T + **Exclude**``: `T` extends `U` ? `never` : `T` Exclude from T those types that are assignable to U diff --git a/www/apps/docs/content/references/pricing/types/ModuleJoinerConfig.mdx b/www/apps/docs/content/references/pricing/types/ModuleJoinerConfig.mdx index e6b351009163d..47d3075bafdc0 100644 --- a/www/apps/docs/content/references/pricing/types/ModuleJoinerConfig.mdx +++ b/www/apps/docs/content/references/pricing/types/ModuleJoinerConfig.mdx @@ -6,4 +6,4 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # ModuleJoinerConfig - **ModuleJoinerConfig**: [Omit](Omit.mdx)<[JoinerServiceConfig](../interfaces/JoinerServiceConfig.mdx), `"serviceName"` \| `"primaryKeys"` \| `"relationships"` \| `"extends"`> & { databaseConfig?: { extraFields?: Record<string, { defaultValue?: string ; nullable?: boolean ; options?: Record<string, unknown> ; type: `"date"` \| `"time"` \| `"datetime"` \| `"bigint"` \| `"blob"` \| `"uint8array"` \| `"array"` \| `"enumArray"` \| `"enum"` \| `"json"` \| `"integer"` \| `"smallint"` \| `"tinyint"` \| `"mediumint"` \| `"float"` \| `"double"` \| `"boolean"` \| `"decimal"` \| `"string"` \| `"uuid"` \| `"text"` }> ; idPrefix?: string ; tableName?: string } ; extends?: { fieldAlias?: Record<string, string \| { forwardArgumentsOnPath: string[] ; path: string }> ; relationship: [ModuleJoinerRelationship](ModuleJoinerRelationship.mdx) ; serviceName: string }[] ; isLink?: boolean ; isReadOnlyLink?: boolean ; linkableKeys?: Record<string, string> ; primaryKeys?: string[] ; relationships?: [ModuleJoinerRelationship](ModuleJoinerRelationship.mdx)[] ; schema?: string ; serviceName?: string } + **ModuleJoinerConfig**: [Omit](Omit.mdx)<[JoinerServiceConfig](../interfaces/JoinerServiceConfig.mdx), "serviceName" \| "primaryKeys" \| "relationships" \| "extends"> & ``{ databaseConfig?: { extraFields?: Record<string, { defaultValue?: string ; nullable?: boolean ; options?: Record<string, unknown> ; type: "date" \| "time" \| "datetime" \| bigint \| "blob" \| "uint8array" \| "array" \| "enumArray" \| "enum" \| "json" \| "integer" \| "smallint" \| "tinyint" \| "mediumint" \| "float" \| "double" \| "boolean" \| "decimal" \| "string" \| "uuid" \| "text" }> ; idPrefix?: string ; tableName?: string } ; extends?: { fieldAlias?: Record<string, string \| { forwardArgumentsOnPath: string[] ; path: string }> ; relationship: [ModuleJoinerRelationship](ModuleJoinerRelationship.mdx) ; serviceName: string }[] ; isLink?: boolean ; isReadOnlyLink?: boolean ; linkableKeys?: Record<string, string> ; primaryKeys?: string[] ; relationships?: [ModuleJoinerRelationship](ModuleJoinerRelationship.mdx)[] ; schema?: string ; serviceName?: string }`` diff --git a/www/apps/docs/content/references/pricing/types/ModuleJoinerRelationship.mdx b/www/apps/docs/content/references/pricing/types/ModuleJoinerRelationship.mdx index d8a280b5bf97b..ef030e0da499f 100644 --- a/www/apps/docs/content/references/pricing/types/ModuleJoinerRelationship.mdx +++ b/www/apps/docs/content/references/pricing/types/ModuleJoinerRelationship.mdx @@ -6,4 +6,4 @@ import ParameterTypes from "@site/src/components/ParameterTypes" # ModuleJoinerRelationship - **ModuleJoinerRelationship**: [JoinerRelationship](JoinerRelationship.mdx) & { deleteCascade?: boolean ; isInternalService?: boolean } + **ModuleJoinerRelationship**: [JoinerRelationship](JoinerRelationship.mdx) & ``{ deleteCascade?: boolean ; isInternalService?: boolean }`` diff --git a/www/apps/docs/content/references/services/classes/ProductCategory.mdx b/www/apps/docs/content/references/services/classes/ProductCategory.mdx index 2ce933d0c91ae..392aa9119a40e 100644 --- a/www/apps/docs/content/references/services/classes/ProductCategory.mdx +++ b/www/apps/docs/content/references/services/classes/ProductCategory.mdx @@ -82,6 +82,15 @@ A product category can be used to categorize products into a hierarchy of catego "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "An optional key-value map with additional details", + "optional": false, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "name", "type": "`string`", diff --git a/www/apps/docs/content/references/services/interfaces/BulkUpdateInventoryLevelInput.mdx b/www/apps/docs/content/references/services/interfaces/BulkUpdateInventoryLevelInput.mdx index 8d7a9b9bed38a..a1770b2b8beb4 100644 --- a/www/apps/docs/content/references/services/interfaces/BulkUpdateInventoryLevelInput.mdx +++ b/www/apps/docs/content/references/services/interfaces/BulkUpdateInventoryLevelInput.mdx @@ -14,7 +14,7 @@ The attributes to update in an inventory level. The inventory level is identifie { "name": "incoming_quantity", "type": "`number`", - "description": "", + "description": "The incoming quantity of the associated inventory item in the associated location.", "optional": true, "defaultValue": "", "expandable": false, @@ -41,7 +41,7 @@ The attributes to update in an inventory level. The inventory level is identifie { "name": "stocked_quantity", "type": "`number`", - "description": "", + "description": "The stocked quantity of the associated inventory item in the associated location.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/services/interfaces/Context.mdx b/www/apps/docs/content/references/services/interfaces/Context.mdx index 0acfa56922a60..79c6336f76fd2 100644 --- a/www/apps/docs/content/references/services/interfaces/Context.mdx +++ b/www/apps/docs/content/references/services/interfaces/Context.mdx @@ -28,7 +28,7 @@ A shared context object that is used to share resources between the application { "name": "enableNestedTransactions", "type": "`boolean`", - "description": "a boolean value indicating whether nested transactions are enabled.", + "description": "A boolean value indicating whether nested transactions are enabled.", "optional": true, "defaultValue": "", "expandable": false, @@ -55,7 +55,7 @@ A shared context object that is used to share resources between the application { "name": "transactionId", "type": "`string`", - "description": "a string indicating the ID of the current transaction.", + "description": "A string indicating the ID of the current transaction.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/services/interfaces/CreateInventoryItemInput.mdx b/www/apps/docs/content/references/services/interfaces/CreateInventoryItemInput.mdx index 08c89f099324b..75bd9d0db226b 100644 --- a/www/apps/docs/content/references/services/interfaces/CreateInventoryItemInput.mdx +++ b/www/apps/docs/content/references/services/interfaces/CreateInventoryItemInput.mdx @@ -86,7 +86,7 @@ The details of the inventory item to be created. { "name": "requires_shipping", "type": "`boolean`", - "description": "", + "description": "Whether the inventory item requires shipping.", "optional": true, "defaultValue": "", "expandable": false, diff --git a/www/apps/docs/content/references/services/interfaces/MoneyAmountDTO.mdx b/www/apps/docs/content/references/services/interfaces/MoneyAmountDTO.mdx index 59f28c36b96c6..9793735e63cb9 100644 --- a/www/apps/docs/content/references/services/interfaces/MoneyAmountDTO.mdx +++ b/www/apps/docs/content/references/services/interfaces/MoneyAmountDTO.mdx @@ -71,7 +71,7 @@ A money amount's data. A money amount represents a price. "description": "The details of the relation between the money amount and its associated price set.", "optional": true, "defaultValue": "", - "expandable": false, + "expandable": true, "children": [] } ]} /> diff --git a/www/apps/docs/content/references/services/types/ProductCategoryInput.mdx b/www/apps/docs/content/references/services/types/ProductCategoryInput.mdx index 3353d7b49be6f..95808d069de27 100644 --- a/www/apps/docs/content/references/services/types/ProductCategoryInput.mdx +++ b/www/apps/docs/content/references/services/types/ProductCategoryInput.mdx @@ -38,6 +38,15 @@ import ParameterTypes from "@site/src/components/ParameterTypes" "expandable": false, "children": [] }, + { + "name": "metadata", + "type": "`Record`", + "description": "", + "optional": true, + "defaultValue": "", + "expandable": false, + "children": [] + }, { "name": "parent_category", "type": "[ProductCategory](../classes/ProductCategory.mdx) \\| `null`", diff --git a/www/apps/docs/content/upgrade-guides/medusa-core/1-18.md b/www/apps/docs/content/upgrade-guides/medusa-core/1-18.md index 38fd5bbd84820..69d541a1b2ef2 100644 --- a/www/apps/docs/content/upgrade-guides/medusa-core/1-18.md +++ b/www/apps/docs/content/upgrade-guides/medusa-core/1-18.md @@ -36,3 +36,15 @@ npm install @medusajs/medusa@1.18 ``` To avoid unexpected issues with dependencies, it's also recommended to update all other Medusa plugins or packages you have installed. + +--- + +## Actions Required + +### Run Migrations + +After updating your Medusa server and before running it, run the following command to run the latest migrations: + +```bash +npx medusa migrations run +``` diff --git a/www/apps/docs/content/upgrade-guides/medusa-core/1-3-8.md b/www/apps/docs/content/upgrade-guides/medusa-core/1-3-8.md index 0fd5d46585ca4..38132bb14f4f7 100644 --- a/www/apps/docs/content/upgrade-guides/medusa-core/1-3-8.md +++ b/www/apps/docs/content/upgrade-guides/medusa-core/1-3-8.md @@ -26,7 +26,7 @@ npm install medusa-interfaces@latest ### Use Legacy Peer Dependencies Option -:::caution +:::warning This solution can be used as a workaround and should be used with caution to avoid any issues while using Medusa. diff --git a/www/apps/docs/content/user-guide.mdx b/www/apps/docs/content/user-guide.mdx index 1b7b68ba67ce3..3c48236d5d503 100644 --- a/www/apps/docs/content/user-guide.mdx +++ b/www/apps/docs/content/user-guide.mdx @@ -57,7 +57,7 @@ At the top right you’ll find a ) } diff --git a/www/apps/docs/src/theme/Admonition/Icon/Note.tsx b/www/apps/docs/src/theme/Admonition/Icon/Note.tsx index 9fb7e1558cd27..7075c76b689fa 100644 --- a/www/apps/docs/src/theme/Admonition/Icon/Note.tsx +++ b/www/apps/docs/src/theme/Admonition/Icon/Note.tsx @@ -11,7 +11,7 @@ export default function AdmonitionIconNote({ diff --git a/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx b/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx index 0da5665b57f04..62e9e96b20fca 100644 --- a/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx +++ b/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx @@ -1,19 +1,7 @@ -import { LightBulbSolid } from "@medusajs/icons" import type { IconProps } from "@medusajs/icons/dist/types" -import clsx from "clsx" import React from "react" +import AdmonitionIconNote from "./Note" -export default function AdmonitionIconTip({ - className, - ...props -}: IconProps): JSX.Element { - return ( - - ) +export default function AdmonitionIconTip(props: IconProps): JSX.Element { + return } diff --git a/www/apps/docs/src/theme/Admonition/Layout/index.tsx b/www/apps/docs/src/theme/Admonition/Layout/index.tsx index d07c3fd0abd9d..2a23771934a4a 100644 --- a/www/apps/docs/src/theme/Admonition/Layout/index.tsx +++ b/www/apps/docs/src/theme/Admonition/Layout/index.tsx @@ -6,12 +6,16 @@ import type { Props } from "@theme/Admonition/Layout" function AdmonitionContainer({ className, children, + type, }: Pick & { children: ReactNode }) { return (
) { return {icon} } -function AdmonitionContent({ children }: Pick) { +function AdmonitionContent({ + children, + title, + type, +}: Pick) { return children ? (
*:last-child]:mb-0", "[&>p>code]:px-0.5 [&>p>code]:text-code-label" )} > + {title && ( + + {transformAdmonitionTitle(title)} + + )} {children}
) : null } export default function AdmonitionLayout(props: Props): JSX.Element { - const { type, icon, children, className } = props + const { type, icon, children, className, title } = props return ( - {children} + + {children} + ) } + +function transformAdmonitionTitle(title: T): T | string { + if (typeof title !== "string") { + return title + } + switch (title) { + case "note": + case "tip": + case "danger": + case "warning": + case "info": + case "caution": + return title.charAt(0).toUpperCase + title.substring(1) + default: + return title + } +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Caution.tsx b/www/apps/docs/src/theme/Admonition/Type/Caution.tsx new file mode 100644 index 0000000000000..0addec8353294 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Caution.tsx @@ -0,0 +1,34 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Caution" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconWarning from "@theme/Admonition/Icon/Warning" + +const infimaClassName = "alert alert--warning" + +const defaultProps = { + icon: , + title: ( + + Caution + + ), +} + +// TODO remove before v4: Caution replaced by Warning +// see https://github.com/facebook/docusaurus/issues/7558 +export default function AdmonitionTypeCaution(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Danger.tsx b/www/apps/docs/src/theme/Admonition/Type/Danger.tsx new file mode 100644 index 0000000000000..7a93418a1f46d --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Danger.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Danger" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconDanger from "@theme/Admonition/Icon/Danger" + +const infimaClassName = "alert alert--danger" + +const defaultProps = { + icon: , + title: ( + + Danger + + ), +} + +export default function AdmonitionTypeDanger(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Info.tsx b/www/apps/docs/src/theme/Admonition/Type/Info.tsx new file mode 100644 index 0000000000000..1823fc71d4638 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Info.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Info" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconInfo from "@theme/Admonition/Icon/Info" + +const infimaClassName = "alert alert--info" + +const defaultProps = { + icon: , + title: ( + + Info + + ), +} + +export default function AdmonitionTypeInfo(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Note.tsx b/www/apps/docs/src/theme/Admonition/Type/Note.tsx new file mode 100644 index 0000000000000..bca2b2f08f7c9 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Note.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Note" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconNote from "@theme/Admonition/Icon/Note" + +const infimaClassName = "alert alert--secondary" + +const defaultProps = { + icon: , + title: ( + + Note + + ), +} + +export default function AdmonitionTypeNote(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Tip.tsx b/www/apps/docs/src/theme/Admonition/Type/Tip.tsx new file mode 100644 index 0000000000000..66fad7c909bf4 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Tip.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Tip" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconTip from "@theme/Admonition/Icon/Tip" + +const infimaClassName = "alert alert--success" + +const defaultProps = { + icon: , + title: ( + + Tip + + ), +} + +export default function AdmonitionTypeTip(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Warning.tsx b/www/apps/docs/src/theme/Admonition/Type/Warning.tsx new file mode 100644 index 0000000000000..d5445b0cc28e4 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Warning.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Warning" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconWarning from "@theme/Admonition/Icon/Warning" + +const infimaClassName = "alert alert--warning" + +const defaultProps = { + icon: , + title: ( + + Warning + + ), +} + +export default function AdmonitionTypeWarning(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Tabs/index.tsx b/www/apps/docs/src/theme/Tabs/index.tsx index dffe008d2efd4..b6dfed9178ad8 100644 --- a/www/apps/docs/src/theme/Tabs/index.tsx +++ b/www/apps/docs/src/theme/Tabs/index.tsx @@ -110,7 +110,7 @@ function TabList({ return (
@@ -146,29 +148,28 @@ function TabList({ onClick={handleTabChange} {...attributes} className={clsx( - isCodeTabs && + isCodeTabs && [ "text-compact-small-plus py-0.25 border border-solid border-transparent whitespace-nowrap rounded-full [&:not(:first-child)]:ml-0.25", - "!mt-0 cursor-pointer", - attributes?.className, - isCodeTabs && "z-[2] flex justify-center items-center", - isCodeTabs && + "z-[2] flex justify-center items-center", selectedValue !== value && - "text-medusa-code-text-subtle hover:!bg-medusa-code-bg-base", - isCodeTabs && + "text-medusa-code-text-subtle hover:!bg-medusa-code-bg-base", selectedValue === value && - "text-medusa-code-text-base border border-solid border-medusa-code-border bg-medusa-code-bg-base xs:!border-none xs:!bg-transparent", - !isCodeTabs && - "border-0 border-b-[3px] rounded inline-flex p-1 transition-[background-color] duration-200 ease-ease", - !isCodeTabs && + "text-medusa-code-text-base border border-solid border-medusa-code-border bg-medusa-code-bg-base xs:!border-none xs:!bg-transparent", + attributes?.badge && + "[&_.badge]:ml-0.5 [&_.badge]:py-0.125 [&_.badge]:px-[6px] [&_.badge]:rounded-full pl-0.75 pr-0.25", + !attributes?.badge && "px-0.75", + ], + !isCodeTabs && [ + "[&:not(:last-child)]:mr-0.5 px-0.75 py-[6px] txt-compact-small-plus", + "border-0 rounded-full transition-shadow duration-200 ease-ease", selectedValue === value && - "border-solid border-medusa-fg-base rounded-b-none", - !isCodeTabs && + "text-medusa-fg-base shadow-card-rest dark:shadow-card-rest-dark", selectedValue !== value && - "text-medusa-fg-subtle", - (!isCodeTabs || !attributes?.badge) && "px-0.75", - isCodeTabs && - attributes?.badge && - "[&_.badge]:ml-0.5 [&_.badge]:py-0.125 [&_.badge]:px-[6px] [&_.badge]:rounded-full pl-0.75 pr-0.25" + "text-medusa-fg-subtle hover:text-medusa-fg-base", + "flex gap-0.5", + ], + "!mt-0 cursor-pointer", + attributes?.className )} > {label ?? value} @@ -251,8 +252,7 @@ export default function Tabs(props: TabsProps): JSX.Element { "tabs-wrapper", props.wrapperClassName, isCodeTabs && "code-tabs", - !isCodeTabs && - "bg-docs-bg-surface p-1 border border-solid border-medusa-border-base rounded" + !isCodeTabs && "my-4" )} >