From 3086f8b0163c20413d1fca6cf4ec610d146b81ea Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Fri, 3 Mar 2023 14:24:33 +0200 Subject: [PATCH 01/12] docs: added script to ignore builds in vercel (#3370) * docs: added script for vercel builds * fix exit --- www/docs/vercel-ignore.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 www/docs/vercel-ignore.sh diff --git a/www/docs/vercel-ignore.sh b/www/docs/vercel-ignore.sh new file mode 100644 index 0000000000..c82fcd1adb --- /dev/null +++ b/www/docs/vercel-ignore.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +current_branch=$(git branch --show-current) + +if [[ "$VERCEL_DEPLOY_BRANCHES" == *"$current_branch"* ]]; then + echo "Branch allowed to deploy" + exit 1; +else + echo "Branch not allowed to deploy" + exit 0; +fi \ No newline at end of file From 0d7725d3d387cc1d957d5de36c80eb3c27bb0c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Riedm=C3=BCller?= <33628348+hanslissi@users.noreply.github.com> Date: Mon, 6 Mar 2023 09:40:20 +0100 Subject: [PATCH 02/12] docs: fix env variable name in sendgrid (#3382) I think this reference is wrong. --- docs/content/add-plugins/sendgrid.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/add-plugins/sendgrid.mdx b/docs/content/add-plugins/sendgrid.mdx index d524ab7cb4..fcfc25be87 100644 --- a/docs/content/add-plugins/sendgrid.mdx +++ b/docs/content/add-plugins/sendgrid.mdx @@ -3917,7 +3917,7 @@ Then, in your `.env` file add the API key you created earlier as well as the sen ```bash SENDGRID_API_KEY= -SENDGRID_FROM= +SENDGRID_FROM= ``` Make sure to replace the `` with the SendGrid API key and the `` with the email you’re using in SendGrid as the single sender. From ba5d34efba58018a27845163cd20cc05b9783c01 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 6 Mar 2023 14:39:38 +0200 Subject: [PATCH 03/12] docs: migrate netlify redirects to vercel redirects (#3387) * docs: added redirects for vercel * fixed vercel error --- www/docs/vercel.json | 120 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 www/docs/vercel.json diff --git a/www/docs/vercel.json b/www/docs/vercel.json new file mode 100644 index 0000000000..2cbc8c3609 --- /dev/null +++ b/www/docs/vercel.json @@ -0,0 +1,120 @@ +{ + "redirects": [ + { + "source": "/api", + "destination": "/api/store" + }, + { + "source": "/api/store/auth/(.*)", + "destination": "/api/store/#tag/Auth" + }, + { + "source": "/api/store/cart/(.*)", + "destination": "/api/store/#tag/Cart" + }, + { + "source": "/api/store/collection/(.*)", + "destination": "/api/store/#tag/Collection" + }, + { + "source": "/api/store/product/(.*)", + "destination": "/api/store/#tag/Product" + }, + { + "source": "/api/admin/auth/(.*)", + "destination": "/api/admin/#tag/Auth" + }, + { + "source": "/api/admin/users/(.*)", + "destination": "/api/admin/#tag/User" + }, + { + "source": "/how-to/headless-ecommerce-store-with-gatsby-contentful-medusa", + "destination": "/add-plugins/contentful" + }, + { + "source": "/how-to/deploying-on-heroku", + "destination": "/deployments/server/deploying-on-heroku" + }, + { + "source": "/admin/introduction", + "destination": "/admin/quickstart" + }, + { + "source": "/admin/quickstart/quick-start", + "destination": "/admin/quickstart" + }, + { + "source": "/admin/quickstart", + "destination": "/admin/quickstart" + }, + { + "source": "/quickstart/starters/nextjs-medusa-starter", + "destination": "/starters/nextjs-medusa-starter" + }, + { + "source": "/quickstart/starters/gatsby-medusa-starter", + "destination": "/starters/gatsby-medusa-starter" + }, + { + "source": "/how-to/create-medusa-app", + "destination": "/usage/create-medusa-app" + }, + { + "source": "/guides/plugins", + "destination": "/advanced/backend/plugins/overview" + }, + { + "source": "/how-to/deploying-admin-on-netlify", + "destination": "/deployments/admin/deploying-on-netlify" + }, + { + "source": "/how-to/deploying-on-digital-ocean/", + "destination": "/deployments/server/deploying-on-digital-ocean" + }, + { + "source": "/how-to/deploying-on-qovery/", + "destination": "/deployments/server/deploying-on-qovery" + }, + { + "source": "/guides/fulfillment-api", + "destination": "/advanced/backend/shipping/add-fulfillment-provider" + }, + { + "source": "/guides/checkouts", + "destination": "/advanced/storefront/how-to-implement-checkout-flow" + }, + { + "source": "/guides/checkouts", + "destination": "/advanced/storefront/how-to-implement-checkout-flow" + }, + { + "source": "/advanced/backend/upgrade-guides/1-7-3", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-7-3" + }, + { + "source": "/advanced/backend/upgrade-guides/1-7-1", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-7-1" + }, + { + "source": "/advanced/backend/upgrade-guides/1-7-0", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-7-0" + }, + { + "source": "/advanced/backend/upgrade-guides/1-6-1", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-6-1" + }, + { + "source": "/advanced/backend/upgrade-guides/1-3-8", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-3-8" + }, + { + "source": "/advanced/backend/upgrade-guides/1-3-6", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-3-6" + }, + { + "source": "/advanced/backend/upgrade-guides/1-3-0", + "destination": "/advanced/backend/upgrade-guides/medusa-core/1-3-0" + } + ] +} \ No newline at end of file From 6496c2080064a8324095b6694c69a80597f5207d Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 6 Mar 2023 19:58:52 +0200 Subject: [PATCH 04/12] docs: improved generation details in migrations guide (#3396) --- .../advanced/backend/migrations/index.md | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/docs/content/advanced/backend/migrations/index.md b/docs/content/advanced/backend/migrations/index.md index 7f2ad29417..f82475a263 100644 --- a/docs/content/advanced/backend/migrations/index.md +++ b/docs/content/advanced/backend/migrations/index.md @@ -7,7 +7,7 @@ addHowToData: true In this document, you’ll learn how to create a [Migration](overview.md) using [Typeorm](https://typeorm.io) on your Medusa server. -## Create Migration File +## Step 1: Create Migration File To create a migration that makes changes to your Medusa schema, run the following command: @@ -19,15 +19,62 @@ This will create the migration file in the path you specify. You can use this wi The migration file must be inside the `src/migrations` directory. When you run the build command, it will be transpiled into the directory `dist/migrations`. The `migrations run` command can only pick up migrations under the `dist/migrations` directory on a Medusa server. This applies to migrations created in a Medusa server, and not in a Medusa plugin. For plugins, check out the [Plugin's Structure section](../plugins/create.md). -:::tip +
+ Generating Migrations for Entities -You can alternatively use Typeorm's `generate` command to generate a Migration file from existing database tables, which requires setting up a data source in Typeorm. Check out Typeorm's documentation to learn [how to create a data source](https://typeorm.io/data-source#creating-a-new-datasource), then use the [generate command](https://typeorm.io/using-cli#generate-a-migration-from-existing-table-schema). + You can alternatively use Typeorm's `generate` command to generate a Migration file from existing entity classes. As Medusa uses v0.2.45 of Typeorm, you have to create a `ormconfig.json` first before using the `generate` command. + +:::note + +Typeorm will be updated to the latest version in v1.8.0 of Medusa. ::: + For example, create the file `ormconfig.json` in the root of your Medusa server with the following content: + + ```json + { + "type": "postgres", + "host": "localhost", + "port": 5432, + "username": "", + "password": "", + "database": "", + "synchronize": true, + "logging": false, + "entities": [ + "dist/models/**/*.js" + ], + "migrations": [ + "dist/migrations/**/*.js" + ], + "cli": { + "entitiesDir": "src/models", + "migrationsDir": "src/migrations" + } + } + ``` + + Make sure to replace ``, ``, and `` with the necessary values for your database connection. + + Then, after creating your entity, run the `build` command: + + ```bash npm2yarn + npm run build + ``` + + Finally, run the following command to generate a Migration for your new entity: + + ```bash + npx typeorm@0.2.45 migration:generate -n PostCreate + ``` + + Where `PostCreate` is just an example of the name of the migration to generate. The migration will then be generated in `src/migrations/-PostCreate.ts`. You can then skip to step 3 of this guide. +
+ --- -## Write Migration File +## Step 2: Write Migration File The migration file contains the necessary commands to create the database columns, foreign keys, and more. @@ -35,7 +82,7 @@ You can learn more about writing the migration file in You can learn more about --- -## Build Files +## Step 3: Build Files Before you can run the migrations you need to run the build command to transpile the TypeScript files to JavaScript files: @@ -45,7 +92,7 @@ npm run build --- -## Run Migration +## Step 4: Run Migration The last step is to run the migration with the command detailed earlier From aa0d1f32153f82c6219efe5cfc08862db5e5a129 Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Mon, 6 Mar 2023 19:41:12 +0100 Subject: [PATCH 05/12] fix(medusa): Remove default job age option from EventBus (#3388) * fix(medusa): Remove default job age option from EventBus * Create .changeset/spicy-camels-invite.md --- .changeset/spicy-camels-invite.md | 5 +++++ packages/medusa/src/services/event-bus.ts | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 .changeset/spicy-camels-invite.md diff --git a/.changeset/spicy-camels-invite.md b/.changeset/spicy-camels-invite.md new file mode 100644 index 0000000000..04cfbdbc82 --- /dev/null +++ b/.changeset/spicy-camels-invite.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): Remove default job age option from EventBus diff --git a/packages/medusa/src/services/event-bus.ts b/packages/medusa/src/services/event-bus.ts index d7bbf197af..efd394e718 100644 --- a/packages/medusa/src/services/event-bus.ts +++ b/packages/medusa/src/services/event-bus.ts @@ -49,8 +49,6 @@ export type EmitOptions = { } } & JobOptions -const COMPLETED_JOB_TTL = 10000 - /** * Can keep track of multiple subscribers to different events and run the * subscribers when events happen. Events will run asynchronously. @@ -228,9 +226,7 @@ export default class EventBusService { options: Record & EmitOptions = { attempts: 1 } ): Promise { const opts: EmitOptions = { - removeOnComplete: { - age: COMPLETED_JOB_TTL, - }, + removeOnComplete: true, ...options, } From c7eee77bd910cb7208731779ce3500987329d51b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 10:01:40 +0200 Subject: [PATCH 06/12] chore(docs): Removed Docs Announcement Bar (automated) (#3412) Co-authored-by: shahednasser --- www/docs/announcement.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/announcement.json b/www/docs/announcement.json index 58400b37e3..9e26dfeeb6 100644 --- a/www/docs/announcement.json +++ b/www/docs/announcement.json @@ -1 +1 @@ -{"id":"https://github.com/medusajs/medusa/releases/tag/v1.7.11","content":"v1.7.11 is out","isCloseable":true} \ No newline at end of file +{} \ No newline at end of file From ce577f2696aa2181bef8f3096b1a639feabe2714 Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:09:43 +0100 Subject: [PATCH 07/12] feat(medusa): Add global job options for events (#3394) --- .changeset/quick-ravens-lie.md | 5 + .../src/services/__tests__/event-bus.js | 143 ++++++++++++++++++ packages/medusa/src/services/event-bus.ts | 7 + packages/medusa/src/types/global.ts | 20 +++ 4 files changed, 175 insertions(+) create mode 100644 .changeset/quick-ravens-lie.md diff --git a/.changeset/quick-ravens-lie.md b/.changeset/quick-ravens-lie.md new file mode 100644 index 0000000000..d2c75f8d0f --- /dev/null +++ b/.changeset/quick-ravens-lie.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +feat(medusa): Add global job options for events diff --git a/packages/medusa/src/services/__tests__/event-bus.js b/packages/medusa/src/services/__tests__/event-bus.js index 9501351941..0532cc8cba 100644 --- a/packages/medusa/src/services/__tests__/event-bus.js +++ b/packages/medusa/src/services/__tests__/event-bus.js @@ -141,6 +141,149 @@ describe("EventBusService", () => { expect(eventBus.queue_.add).toHaveBeenCalled() }) }) + + describe("successfully adds job to queue with local options", () => { + beforeAll(() => { + jest.resetAllMocks() + const stagedJobRepository = MockRepository({ + find: () => Promise.resolve([]), + }) + + eventBus = new EventBusService({ + logger: loggerMock, + manager: MockManager, + stagedJobRepository, + }) + + eventBus.queue_.add.mockImplementationOnce(() => "hi") + + job = eventBus.emit( + "eventName", + { hi: "1234" }, + { removeOnComplete: 100 } + ) + }) + afterAll(async () => { + await eventBus.stopEnqueuer() + }) + + it("calls queue.add", () => { + expect(eventBus.queue_.add).toHaveBeenCalled() + expect(eventBus.queue_.add).toHaveBeenCalledWith( + { eventName: "eventName", data: { hi: "1234" } }, + { removeOnComplete: 100 } + ) + }) + }) + + describe("successfully adds job to queue with global options", () => { + beforeAll(() => { + jest.resetAllMocks() + const stagedJobRepository = MockRepository({ + find: () => Promise.resolve([]), + }) + + eventBus = new EventBusService( + { + logger: loggerMock, + manager: MockManager, + stagedJobRepository, + }, + { + projectConfig: { event_options: { removeOnComplete: 10 } }, + } + ) + + eventBus.queue_.add.mockImplementationOnce(() => "hi") + + job = eventBus.emit("eventName", { hi: "1234" }) + }) + afterAll(async () => { + await eventBus.stopEnqueuer() + }) + + it("calls queue.add", () => { + expect(eventBus.queue_.add).toHaveBeenCalled() + expect(eventBus.queue_.add).toHaveBeenCalledWith( + { eventName: "eventName", data: { hi: "1234" } }, + { removeOnComplete: 10, attempts: 1 } + ) + }) + }) + + describe("successfully adds job to queue with default options", () => { + beforeAll(() => { + jest.resetAllMocks() + const stagedJobRepository = MockRepository({ + find: () => Promise.resolve([]), + }) + + eventBus = new EventBusService({ + logger: loggerMock, + manager: MockManager, + stagedJobRepository, + }) + + eventBus.queue_.add.mockImplementationOnce(() => "hi") + + job = eventBus.emit("eventName", { hi: "1234" }) + }) + afterAll(async () => { + await eventBus.stopEnqueuer() + }) + + it("calls queue.add", () => { + expect(eventBus.queue_.add).toHaveBeenCalled() + expect(eventBus.queue_.add).toHaveBeenCalledWith( + { eventName: "eventName", data: { hi: "1234" } }, + { removeOnComplete: true, attempts: 1 } + ) + }) + }) + + describe("successfully adds job to queue with local options and global options merged", () => { + beforeAll(() => { + jest.resetAllMocks() + const stagedJobRepository = MockRepository({ + find: () => Promise.resolve([]), + }) + + eventBus = new EventBusService( + { + logger: loggerMock, + manager: MockManager, + stagedJobRepository, + }, + { + projectConfig: { event_options: { removeOnComplete: 10 } }, + } + ) + + eventBus.queue_.add.mockImplementationOnce(() => "hi") + + job = eventBus.emit( + "eventName", + { hi: "1234" }, + { attempts: 10, delay: 1000, backoff: { type: "exponential" } } + ) + }) + afterAll(async () => { + await eventBus.stopEnqueuer() + }) + + it("calls queue.add", () => { + expect(eventBus.queue_.add).toHaveBeenCalled() + expect(eventBus.queue_.add).toHaveBeenCalledWith( + { eventName: "eventName", data: { hi: "1234" } }, + { + removeOnComplete: 10, // global option + attempts: 10, // local option + delay: 1000, // local option + backoff: { type: "exponential" }, // local option + } + ) + }) + }) }) describe("worker", () => { diff --git a/packages/medusa/src/services/event-bus.ts b/packages/medusa/src/services/event-bus.ts index efd394e718..5549b1e36c 100644 --- a/packages/medusa/src/services/event-bus.ts +++ b/packages/medusa/src/services/event-bus.ts @@ -225,8 +225,15 @@ export default class EventBusService { data: T, options: Record & EmitOptions = { attempts: 1 } ): Promise { + const globalEventOptions = this.config_?.projectConfig?.event_options ?? {} + + // The order of precedence for job options is: + // 1. local options + // 2. global options + // 3. default options const opts: EmitOptions = { removeOnComplete: true, + ...globalEventOptions, ...options, } diff --git a/packages/medusa/src/types/global.ts b/packages/medusa/src/types/global.ts index eee037ac01..cf0d08bde5 100644 --- a/packages/medusa/src/types/global.ts +++ b/packages/medusa/src/types/global.ts @@ -3,6 +3,7 @@ import { Request } from "express" import { LoggerOptions } from "typeorm" import { Logger as _Logger } from "winston" import { Customer, User } from "../models" +import { EmitOptions } from "../services/event-bus" import { FindConfig, RequestQueryFields } from "./common" declare global { @@ -114,6 +115,25 @@ export type ConfigModule = { projectConfig: { redis_url?: string + /** + * Global options passed to all `EventBusService.emit` in the core as well as your own emitters. The options are forwarded to Bull's `Queue.add` method. + * + * The global options can be overridden by passing options to `EventBusService.emit` directly. + * + * Note: This will be deprecated as we move to Event Bus module in 1.8 + * + * + * Example + * ```js + * { + * removeOnComplete: { age: 10 }, + * } + * ``` + * + * @see https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queueadd + */ + event_options?: Record & EmitOptions + session_options?: SessionOptions jwt_secret?: string From 9f508c8bd8bee63677504cc8b86f1643579945d8 Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Wed, 8 Mar 2023 15:27:43 +0100 Subject: [PATCH 08/12] fix(medusa): Create migration to ensure correct variant inventory column (#3384) * add migration to ensure quantity is called required quantity * add changeset --- .changeset/spicy-hornets-know.md | 5 +++ .../1671711415179-multi_location.ts | 2 +- .../1678093365811-ensure_required_quantity.ts | 31 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 .changeset/spicy-hornets-know.md create mode 100644 packages/medusa/src/migrations/1678093365811-ensure_required_quantity.ts diff --git a/.changeset/spicy-hornets-know.md b/.changeset/spicy-hornets-know.md new file mode 100644 index 0000000000..f74ba48ba0 --- /dev/null +++ b/.changeset/spicy-hornets-know.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +Fix(medusa): Column naming on migrations diff --git a/packages/medusa/src/migrations/1671711415179-multi_location.ts b/packages/medusa/src/migrations/1671711415179-multi_location.ts index 8f1d9e4464..7531c8fd1e 100644 --- a/packages/medusa/src/migrations/1671711415179-multi_location.ts +++ b/packages/medusa/src/migrations/1671711415179-multi_location.ts @@ -14,7 +14,7 @@ export class multiLocation1671711415179 implements MigrationInterface { `CREATE INDEX "IDX_c2203162ca946a71aeb98390b0" ON "sales_channel_location" ("location_id") ` ) await queryRunner.query( - `CREATE TABLE "product_variant_inventory_item" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "inventory_item_id" text NOT NULL, "variant_id" text NOT NULL, "required_quantity" integer NOT NULL DEFAULT '1', CONSTRAINT "UQ_c9be7c1b11a1a729eb51d1b6bca" UNIQUE ("variant_id", "inventory_item_id"), CONSTRAINT "PK_9a1188b8d36f4d198303b4f7efa" PRIMARY KEY ("id"))` + `CREATE TABLE "product_variant_inventory_item" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "inventory_item_id" text NOT NULL, "variant_id" text NOT NULL, "quantity" integer NOT NULL DEFAULT '1', CONSTRAINT "UQ_c9be7c1b11a1a729eb51d1b6bca" UNIQUE ("variant_id", "inventory_item_id"), CONSTRAINT "PK_9a1188b8d36f4d198303b4f7efa" PRIMARY KEY ("id"))` ) await queryRunner.query( `CREATE INDEX "IDX_c74e8c2835094a37dead376a3b" ON "product_variant_inventory_item" ("inventory_item_id") ` diff --git a/packages/medusa/src/migrations/1678093365811-ensure_required_quantity.ts b/packages/medusa/src/migrations/1678093365811-ensure_required_quantity.ts new file mode 100644 index 0000000000..b07fca4b3d --- /dev/null +++ b/packages/medusa/src/migrations/1678093365811-ensure_required_quantity.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class ensureRequiredQuantity1678093365811 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DO + $$ + BEGIN + ALTER TABLE product_variant_inventory_item + RENAME COLUMN quantity TO required_quantity; + EXCEPTION + WHEN undefined_column THEN + END; + $$; + `) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DO + $$ + BEGIN + ALTER TABLE product_variant_inventory_item + RENAME COLUMN required_quantity TO quantity; + EXCEPTION + WHEN undefined_column THEN + END; + $$; + `) + } +} From 2fe056f4cfd30997229dcfdd2982aa992b1bb30a Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Thu, 9 Mar 2023 08:58:49 +0100 Subject: [PATCH 09/12] chore(release): v1.7.12 --- .changeset/quick-ravens-lie.md | 5 ----- .changeset/spicy-camels-invite.md | 5 ----- .changeset/spicy-hornets-know.md | 5 ----- packages/inventory/CHANGELOG.md | 7 +++++++ packages/inventory/package.json | 4 ++-- packages/medusa/CHANGELOG.md | 10 ++++++++++ packages/medusa/package.json | 2 +- 7 files changed, 20 insertions(+), 18 deletions(-) delete mode 100644 .changeset/quick-ravens-lie.md delete mode 100644 .changeset/spicy-camels-invite.md delete mode 100644 .changeset/spicy-hornets-know.md diff --git a/.changeset/quick-ravens-lie.md b/.changeset/quick-ravens-lie.md deleted file mode 100644 index d2c75f8d0f..0000000000 --- a/.changeset/quick-ravens-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@medusajs/medusa": patch ---- - -feat(medusa): Add global job options for events diff --git a/.changeset/spicy-camels-invite.md b/.changeset/spicy-camels-invite.md deleted file mode 100644 index 04cfbdbc82..0000000000 --- a/.changeset/spicy-camels-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@medusajs/medusa": patch ---- - -fix(medusa): Remove default job age option from EventBus diff --git a/.changeset/spicy-hornets-know.md b/.changeset/spicy-hornets-know.md deleted file mode 100644 index f74ba48ba0..0000000000 --- a/.changeset/spicy-hornets-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@medusajs/medusa": patch ---- - -Fix(medusa): Column naming on migrations diff --git a/packages/inventory/CHANGELOG.md b/packages/inventory/CHANGELOG.md index d1b1269eac..ce78f5972b 100644 --- a/packages/inventory/CHANGELOG.md +++ b/packages/inventory/CHANGELOG.md @@ -1,5 +1,12 @@ # @medusajs/inventory +## 1.0.9 + +### Patch Changes + +- Updated dependencies [[`ce577f269`](https://github.com/medusajs/medusa/commit/ce577f2696aa2181bef8f3096b1a639feabe2714), [`aa0d1f321`](https://github.com/medusajs/medusa/commit/aa0d1f32153f82c6219efe5cfc08862db5e5a129), [`9f508c8bd`](https://github.com/medusajs/medusa/commit/9f508c8bd8bee63677504cc8b86f1643579945d8)]: + - @medusajs/medusa@1.7.12 + ## 1.0.8 ### Patch Changes diff --git a/packages/inventory/package.json b/packages/inventory/package.json index d29d660285..05aedb03d9 100644 --- a/packages/inventory/package.json +++ b/packages/inventory/package.json @@ -1,6 +1,6 @@ { "name": "@medusajs/inventory", - "version": "1.0.8", + "version": "1.0.9", "description": "Inventory Module for Medusa", "main": "dist/index.js", "repository": { @@ -31,7 +31,7 @@ "test:unit": "jest --passWithNoTests" }, "peerDependencies": { - "@medusajs/medusa": "1.7.11", + "@medusajs/medusa": "1.7.12", "medusa-interfaces": "1.3.6" }, "dependencies": { diff --git a/packages/medusa/CHANGELOG.md b/packages/medusa/CHANGELOG.md index 9b1b2e6b82..94bf7bb1cf 100644 --- a/packages/medusa/CHANGELOG.md +++ b/packages/medusa/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 1.7.12 + +### Patch Changes + +- [#3394](https://github.com/medusajs/medusa/pull/3394) [`ce577f269`](https://github.com/medusajs/medusa/commit/ce577f2696aa2181bef8f3096b1a639feabe2714) Thanks [@olivermrbl](https://github.com/olivermrbl)! - feat(medusa): Add global job options for events + +- [#3388](https://github.com/medusajs/medusa/pull/3388) [`aa0d1f321`](https://github.com/medusajs/medusa/commit/aa0d1f32153f82c6219efe5cfc08862db5e5a129) Thanks [@olivermrbl](https://github.com/olivermrbl)! - fix(medusa): Remove default job age option from EventBus + +- [#3384](https://github.com/medusajs/medusa/pull/3384) [`9f508c8bd`](https://github.com/medusajs/medusa/commit/9f508c8bd8bee63677504cc8b86f1643579945d8) Thanks [@pKorsholm](https://github.com/pKorsholm)! - Fix(medusa): Column naming on migrations + ## 1.7.11 ### Patch Changes diff --git a/packages/medusa/package.json b/packages/medusa/package.json index ac8cd37e6a..9161982b98 100644 --- a/packages/medusa/package.json +++ b/packages/medusa/package.json @@ -1,6 +1,6 @@ { "name": "@medusajs/medusa", - "version": "1.7.11", + "version": "1.7.12", "description": "E-commerce for JAMstack", "main": "dist/index.js", "bin": "./cli.js", From e5f0a6009036be727fdcfd673cc524c53baf5f44 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Thu, 9 Mar 2023 10:37:27 +0100 Subject: [PATCH 10/12] chore: Update yarn.lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index ba2ad9d30d..d994a63cb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4737,7 +4737,7 @@ __metadata: typeorm: ^0.2.31 typescript: ^4.4.4 peerDependencies: - "@medusajs/medusa": 1.7.11 + "@medusajs/medusa": 1.7.12 medusa-interfaces: 1.3.6 languageName: unknown linkType: soft From ea28eea251fd18e9cf04d1e2a286b711257a6a78 Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Thu, 9 Mar 2023 12:20:19 +0100 Subject: [PATCH 11/12] docs: Added upgrade guide for v1.7.12 (#3425) * docs: Added upgrade guide for v1.7.12 * Update 1-7-12.md * Update 1-7-12.md --------- Co-authored-by: Shahed Nasser --- .../upgrade-guides/medusa-core/1-3-0.md | 2 +- .../upgrade-guides/medusa-core/1-3-6.md | 2 +- .../upgrade-guides/medusa-core/1-3-8.md | 2 +- .../upgrade-guides/medusa-core/1-6-1.md | 2 +- .../upgrade-guides/medusa-core/1-7-0.md | 2 +- .../upgrade-guides/medusa-core/1-7-1.md | 2 +- .../upgrade-guides/medusa-core/1-7-12.md | 22 +++++++++++++++++++ .../upgrade-guides/medusa-core/1-7-3.md | 2 +- .../upgrade-guides/medusa-core/1-7-6.md | 2 +- 9 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-12.md diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-0.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-0.md index 3f678dc330..592787410d 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-0.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-0.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 description: 'Actions Required for v.1.3.0' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-6.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-6.md index 7fadd7a320..0d2765a1ec 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-6.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-6.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 description: 'Actions Required for v.1.3.0' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-8.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-8.md index 8e1ae46d1f..8cd5233fa0 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-8.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-3-8.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 description: 'Actions Required for v.1.3.0' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-6-1.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-6-1.md index 484313cb47..5eea3bf2ad 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-6-1.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-6-1.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 description: 'Actions Required for v.1.6.1' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-0.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-0.md index d4d8eae1fc..0d0124b5d0 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-0.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-0.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 description: 'Actions Required for v.1.7.0' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-1.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-1.md index 537b8c79bb..e4e5423497 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-1.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-1.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 description: 'Actions Required for v.1.7.1' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-12.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-12.md new file mode 100644 index 0000000000..5d463d4e59 --- /dev/null +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-12.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 1 +description: 'Actions Required for v.1.7.12' +--- + +# v1.7.12 + +Version 1.7.12 of Medusa introduces some database schema changes which require running the migrations command. + +## Overview + +This release contains a migration to ensure that the `product_variant_inventory` table is in its correct state. This is due to a mistake in a previous version where a column name was renamed in an already released migration. This could lead to errors if the migration was applied before the renaming of the column. + +## Actions Required + +### Run Migrations + +After updating your Medusa server and before running it, run the following command to run the latest migrations: + +```bash +medusa migrations run +``` diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-3.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-3.md index 72bba39c01..9262652e10 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-3.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-3.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 description: 'Actions Required for v.1.7.3' --- diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md index 22239540fc..bd3711da3b 100644 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md +++ b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 2 description: 'Actions Required for v.1.7.6' --- From 601d20e7ab293728cd81f0723805841016812120 Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Thu, 9 Mar 2023 16:17:41 +0100 Subject: [PATCH 12/12] chores(medusa): Improve draft order creation perf flow (#3431) --- .changeset/many-wolves-sit.md | 5 + .../__tests__/custom-shipping-option.js | 25 +-- .../src/services/__tests__/draft-order.js | 80 +++++++--- packages/medusa/src/services/cart.ts | 29 ++-- .../src/services/custom-shipping-option.ts | 33 ++-- packages/medusa/src/services/draft-order.ts | 151 ++++++++++++------ packages/medusa/src/services/line-item.ts | 21 ++- packages/medusa/src/types/line-item.ts | 2 + 8 files changed, 226 insertions(+), 120 deletions(-) create mode 100644 .changeset/many-wolves-sit.md diff --git a/.changeset/many-wolves-sit.md b/.changeset/many-wolves-sit.md new file mode 100644 index 0000000000..66b8ab755d --- /dev/null +++ b/.changeset/many-wolves-sit.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +chores(medusa): Improve draft order creation perf flow diff --git a/packages/medusa/src/services/__tests__/custom-shipping-option.js b/packages/medusa/src/services/__tests__/custom-shipping-option.js index 35290b9746..acdf6da157 100644 --- a/packages/medusa/src/services/__tests__/custom-shipping-option.js +++ b/packages/medusa/src/services/__tests__/custom-shipping-option.js @@ -1,5 +1,6 @@ import CustomShippingOptionService from "../custom-shipping-option" -import { MockManager, MockRepository, IdMap } from "medusa-test-utils" + +import { MockManager, MockRepository } from "medusa-test-utils" describe("CustomShippingOptionService", () => { describe("list", () => { @@ -108,20 +109,22 @@ describe("CustomShippingOptionService", () => { await customShippingOptionService.create(customShippingOption) expect(customShippingOptionRepository.create).toHaveBeenCalledTimes(1) - expect(customShippingOptionRepository.create).toHaveBeenCalledWith({ - cart_id: "test-cso-cart", - shipping_option_id: "test-so", - price: 30, - metadata: undefined, - }) + expect(customShippingOptionRepository.create).toHaveBeenCalledWith([ + { + cart_id: "test-cso-cart", + shipping_option_id: "test-so", + price: 30, + }, + ]) expect(customShippingOptionRepository.save).toHaveBeenCalledTimes(1) expect(customShippingOptionRepository.save).toHaveBeenCalledWith({ + 0: { + cart_id: "test-cso-cart", + shipping_option_id: "test-so", + price: 30, + }, id: "test-cso", - cart_id: "test-cso-cart", - shipping_option_id: "test-so", - price: 30, - metadata: undefined, }) }) }) diff --git a/packages/medusa/src/services/__tests__/draft-order.js b/packages/medusa/src/services/__tests__/draft-order.js index d789dee979..90424698d9 100644 --- a/packages/medusa/src/services/__tests__/draft-order.js +++ b/packages/medusa/src/services/__tests__/draft-order.js @@ -35,10 +35,12 @@ describe("DraftOrderService", () => { const lineItemService = { generate: jest.fn().mockImplementation(() => - Promise.resolve({ - title: "test-item", - variant_id: "test-variant", - }) + Promise.resolve([ + { + title: "test-item", + variant_id: "test-variant", + }, + ]) ), create: jest.fn().mockImplementation((data) => data), withTransaction: function () { @@ -88,6 +90,12 @@ describe("DraftOrderService", () => { ...testOrder, }) ), + retrieveWithTotals: jest.fn().mockReturnValue( + Promise.resolve({ + id: "test-cart", + ...testOrder, + }) + ), update: jest.fn(), applyDiscount: jest.fn(), addShippingMethod: jest.fn(), @@ -151,28 +159,37 @@ describe("DraftOrderService", () => { expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1) expect(cartService.addShippingMethod).toHaveBeenCalledWith( - "test-cart", + { + id: "test-cart", + ...testOrder, + }, "test-option", {} ) expect(lineItemService.generate).toHaveBeenCalledTimes(1) expect(lineItemService.generate).toHaveBeenCalledWith( - "test-variant", - "test-region", - 2, + [ + { + variantId: "test-variant", + quantity: 2, + metadata: {}, + unit_price: undefined, + }, + ], { - metadata: {}, - unit_price: undefined, + region_id: "test-region", } ) expect(lineItemService.create).toHaveBeenCalledTimes(1) - expect(lineItemService.create).toHaveBeenCalledWith({ - cart_id: cartId, - title, - variant_id: "test-variant", - }) + expect(lineItemService.create).toHaveBeenCalledWith([ + { + cart_id: cartId, + title, + variant_id: "test-variant", + }, + ]) expect(cartService.applyDiscount).toHaveBeenCalledTimes(0) }) @@ -181,6 +198,8 @@ describe("DraftOrderService", () => { const cartId = "test-cart" const title = "test-item" + const originalTestOrder = { ...testOrder } + testOrder["discounts"] = [{ code: "TEST" }] await draftOrderService.create(testOrder) @@ -200,28 +219,37 @@ describe("DraftOrderService", () => { expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1) expect(cartService.addShippingMethod).toHaveBeenCalledWith( - "test-cart", + { + id: "test-cart", + ...originalTestOrder, + }, "test-option", {} ) expect(lineItemService.generate).toHaveBeenCalledTimes(1) expect(lineItemService.generate).toHaveBeenCalledWith( - "test-variant", - "test-region", - 2, + [ + { + variantId: "test-variant", + quantity: 2, + metadata: {}, + unit_price: undefined, + }, + ], { - metadata: {}, - unit_price: undefined, + region_id: "test-region", } ) expect(lineItemService.create).toHaveBeenCalledTimes(1) - expect(lineItemService.create).toHaveBeenCalledWith({ - cart_id: cartId, - title, - variant_id: "test-variant", - }) + expect(lineItemService.create).toHaveBeenCalledWith([ + { + cart_id: cartId, + title, + variant_id: "test-variant", + }, + ]) expect(cartService.update).toHaveBeenCalledTimes(1) expect(cartService.update).toHaveBeenCalledWith(cartId, { diff --git a/packages/medusa/src/services/cart.ts b/packages/medusa/src/services/cart.ts index e06000041f..903483694b 100644 --- a/packages/medusa/src/services/cart.ts +++ b/packages/medusa/src/services/cart.ts @@ -36,7 +36,7 @@ import { TotalField, WithRequiredProperty, } from "../types/common" -import { buildQuery, setMetadata } from "../utils" +import { buildQuery, isString, setMetadata } from "../utils" import { FlagRouter } from "../utils/flag-router" import { validateEmail } from "../utils/is-email" import { PaymentSessionInput } from "../types/payment" @@ -2060,27 +2060,30 @@ class CartService extends TransactionBaseService { * Shipping Option is a possible way to ship an order. Shipping Methods may * also have additional details in the data field such as an id for a package * shop. - * @param cartId - the id of the cart to add shipping method to + * @param cartOrId - the id or the cart to add shipping method to * @param optionId - id of shipping option to add as valid method * @param data - the fulmillment data for the method * @return the result of the update operation */ async addShippingMethod( - cartId: string, + cartOrId: string | Cart, optionId: string, data: Record = {} ): Promise { return await this.atomicPhase_( async (transactionManager: EntityManager) => { - const cart = await this.retrieveWithTotals(cartId, { - relations: [ - "shipping_methods", - "shipping_methods.shipping_option", - "items", - "items.variant", - "items.variant.product", - ], - }) + const cart = !isString(cartOrId) + ? cartOrId + : await this.retrieveWithTotals(cartOrId, { + relations: [ + "shipping_methods", + "shipping_methods.shipping_option", + "items", + "items.variant", + "items.variant.product", + "payment_sessions", + ], + }) const cartCustomShippingOptions = await this.customShippingOptionService_ @@ -2140,7 +2143,7 @@ class CartService extends TransactionBaseService { ) } - const updatedCart = await this.retrieve(cartId, { + const updatedCart = await this.retrieve(cart.id, { relations: ["discounts", "discounts.rule", "shipping_methods"], }) diff --git a/packages/medusa/src/services/custom-shipping-option.ts b/packages/medusa/src/services/custom-shipping-option.ts index 84dd2efeb8..034576a613 100644 --- a/packages/medusa/src/services/custom-shipping-option.ts +++ b/packages/medusa/src/services/custom-shipping-option.ts @@ -1,5 +1,5 @@ import { MedusaError } from "medusa-core-utils" -import { EntityManager } from "typeorm" +import { DeepPartial, EntityManager } from "typeorm" import { TransactionBaseService } from "../interfaces" import { CustomShippingOption } from "../models" import { CustomShippingOptionRepository } from "../repositories/custom-shipping-option" @@ -86,23 +86,28 @@ class CustomShippingOptionService extends TransactionBaseService { * @param config - any configurations if needed, including meta data * @return resolves to the creation result */ - async create( - data: CreateCustomShippingOptionInput - ): Promise { - const { cart_id, shipping_option_id, price, metadata } = data - - const manager = this.manager_ + async create< + T = CreateCustomShippingOptionInput | CreateCustomShippingOptionInput[], + TResult = T extends CreateCustomShippingOptionInput[] + ? CustomShippingOption[] + : CustomShippingOption + >(data: T): Promise { + const manager = this.transactionManager_ ?? this.manager_ const customShippingOptionRepo = manager.getCustomRepository( this.customShippingOptionRepository_ ) + const data_ = ( + Array.isArray(data) ? data : [data] + ) as DeepPartial[] - const customShippingOption = customShippingOptionRepo.create({ - cart_id, - shipping_option_id, - price, - metadata, - }) - return await customShippingOptionRepo.save(customShippingOption) + const customShippingOptions = customShippingOptionRepo.create(data_) + const shippingOptions = await customShippingOptionRepo.save( + customShippingOptions + ) + + return (Array.isArray(data) + ? shippingOptions + : shippingOptions[0]) as unknown as TResult } } diff --git a/packages/medusa/src/services/draft-order.ts b/packages/medusa/src/services/draft-order.ts index b91ff2a2bc..f3663bdd4d 100644 --- a/packages/medusa/src/services/draft-order.ts +++ b/packages/medusa/src/services/draft-order.ts @@ -1,7 +1,13 @@ import { isDefined, MedusaError } from "medusa-core-utils" import { Brackets, EntityManager, FindManyOptions, UpdateResult } from "typeorm" import { TransactionBaseService } from "../interfaces" -import { CartType, DraftOrder, DraftOrderStatus } from "../models" +import { + CartType, + DraftOrder, + DraftOrderStatus, + LineItem, + ShippingMethod, +} from "../models" import { DraftOrderRepository } from "../repositories/draft-order" import { OrderRepository } from "../repositories/order" import { PaymentRepository } from "../repositories/payment" @@ -14,6 +20,7 @@ import EventBusService from "./event-bus" import LineItemService from "./line-item" import ProductVariantService from "./product-variant" import ShippingOptionService from "./shipping-option" +import { GenerateInputData } from "../types/line-item" type InjectedDependencies = { manager: EntityManager @@ -271,7 +278,7 @@ class DraftOrderService extends TransactionBaseService { const cartServiceTx = this.cartService_.withTransaction(transactionManager) - const createdCart = await cartServiceTx.create({ + let createdCart = await cartServiceTx.create({ type: CartType.DRAFT_ORDER, ...rawCart, }) @@ -293,64 +300,108 @@ class DraftOrderService extends TransactionBaseService { const lineItemServiceTx = this.lineItemService_.withTransaction(transactionManager) - for (const item of items || []) { + const itemsToGenerate: GenerateInputData[] = [] + const itemsToCreate: Partial[] = [] + + // prepare that for next steps + ;(items ?? []).forEach((item) => { if (item.variant_id) { - const line = await lineItemServiceTx.generate( - item.variant_id, - data.region_id, - item.quantity, - { - metadata: item?.metadata || {}, - unit_price: item.unit_price, - } - ) - - await lineItemServiceTx.create({ - ...line, - cart_id: createdCart.id, - }) - } else { - let price - if (typeof item.unit_price === `undefined` || item.unit_price < 0) { - price = 0 - } else { - price = item.unit_price - } - - // custom line items can be added to a draft order - await lineItemServiceTx.create({ - cart_id: createdCart.id, - has_shipping: true, - title: item.title || "Custom item", - allow_discounts: false, - unit_price: price, + itemsToGenerate.push({ + variantId: item.variant_id, quantity: item.quantity, + metadata: item.metadata, + unit_price: item.unit_price, }) + return } + + let price + if (!isDefined(item.unit_price) || item.unit_price < 0) { + price = 0 + } else { + price = item.unit_price + } + + itemsToCreate.push({ + cart_id: createdCart.id, + has_shipping: true, + title: item.title || "Custom item", + allow_discounts: false, + unit_price: price, + quantity: item.quantity, + }) + }) + + const promises: Promise[] = [] + + // generate line item link to a variant + if (itemsToGenerate.length) { + const generatedLines = await lineItemServiceTx.generate( + itemsToGenerate, + { + region_id: data.region_id, + } + ) + + const toCreate = generatedLines.map((line) => ({ + ...line, + cart_id: createdCart.id, + })) + + promises.push(lineItemServiceTx.create(toCreate)) } + // custom line items can be added to a draft order + if (itemsToCreate.length) { + promises.push(lineItemServiceTx.create(itemsToCreate)) + } + + const shippingMethodToCreate: Partial[] = [] + + shipping_methods.forEach((method) => { + if (isDefined(method.price)) { + shippingMethodToCreate.push({ + shipping_option_id: method.option_id, + cart_id: createdCart.id, + price: method.price, + }) + return + } + }) + + if (shippingMethodToCreate.length) { + await this.customShippingOptionService_ + .withTransaction(transactionManager) + .create(shippingMethodToCreate) + } + + createdCart = await cartServiceTx.retrieveWithTotals(createdCart.id, { + relations: [ + "shipping_methods", + "shipping_methods.shipping_option", + "items", + "items.variant", + "items.variant.product", + "payment_sessions", + ], + }) + + shipping_methods.forEach((method) => { + promises.push( + cartServiceTx.addShippingMethod( + createdCart, + method.option_id, + method.data + ) + ) + }) + + await Promise.all(promises) + if (discounts?.length) { await cartServiceTx.update(createdCart.id, { discounts }) } - for (const method of shipping_methods) { - if (typeof method.price !== "undefined") { - await this.customShippingOptionService_ - .withTransaction(transactionManager) - .create({ - shipping_option_id: method.option_id, - cart_id: createdCart.id, - price: method.price, - }) - } - - await cartServiceTx.addShippingMethod( - createdCart.id, - method.option_id, - method.data - ) - } - return result } ) diff --git a/packages/medusa/src/services/line-item.ts b/packages/medusa/src/services/line-item.ts index f1314a31ee..c08f4bc90d 100644 --- a/packages/medusa/src/services/line-item.ts +++ b/packages/medusa/src/services/line-item.ts @@ -220,9 +220,11 @@ class LineItemService extends TransactionBaseService { quantity: quantity as number, } : variantIdOrData + const resolvedContext = isString(variantIdOrData) ? context : (regionIdOrContext as GenerateLineItemContext) + const regionId = ( isString(variantIdOrData) ? regionIdOrContext @@ -233,6 +235,10 @@ class LineItemService extends TransactionBaseService { Array.isArray(data) ? data : [data] ) as GenerateInputData[] + const resolvedDataMap = new Map( + resolvedData.map((d) => [d.variantId, d]) + ) + const variants = await this.productVariantService_.list( { id: resolvedData.map((d) => d.variantId), @@ -247,7 +253,11 @@ class LineItemService extends TransactionBaseService { for (const variant of variants) { variantsMap.set(variant.id, variant) - if (resolvedContext.unit_price == null) { + const variantResolvedData = resolvedDataMap.get(variant.id) + if ( + resolvedContext.unit_price == null && + variantResolvedData?.unit_price == null + ) { variantIdsToCalculatePricingFor.push(variant.id) } } @@ -274,6 +284,8 @@ class LineItemService extends TransactionBaseService { variantData.quantity, { ...resolvedContext, + unit_price: variantData.unit_price ?? resolvedContext.unit_price, + metadata: variantData.metadata ?? resolvedContext.metadata, variantPricing, } ) @@ -313,8 +325,6 @@ class LineItemService extends TransactionBaseService { variantPricing: ProductVariantPricing } ): Promise { - const transactionManager = this.transactionManager_ ?? this.manager_ - let unit_price = Number(context.unit_price) < 0 ? 0 : context.unit_price let unitPriceIncludesTax = false let shouldMerge = false @@ -350,9 +360,8 @@ class LineItemService extends TransactionBaseService { rawLineItem.order_edit_id = context.order_edit_id || null - const lineItemRepo = transactionManager.getCustomRepository( - this.lineItemRepository_ - ) + const manager = this.transactionManager_ ?? this.manager_ + const lineItemRepo = manager.getCustomRepository(this.lineItemRepository_) const lineItem = lineItemRepo.create(rawLineItem) lineItem.variant = variant as ProductVariant diff --git a/packages/medusa/src/types/line-item.ts b/packages/medusa/src/types/line-item.ts index c1aa714896..8aa12d4beb 100644 --- a/packages/medusa/src/types/line-item.ts +++ b/packages/medusa/src/types/line-item.ts @@ -3,6 +3,8 @@ import { CalculationContextData } from "./totals" export type GenerateInputData = { variantId: string quantity: number + metadata?: Record + unit_price?: number } export type GenerateLineItemContext = {