From cdb01e073b4e9cbe5fe38bbe799976e675d9571d Mon Sep 17 00:00:00 2001 From: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:33:16 +0100 Subject: [PATCH] feat(link-modules): Cart, Payment Collection link definition (#6508) * Add cart payment collection joiner confg * fix migration * chore: Exclude inventory tests * remove jest ignore * add back payment module --- .../__tests__/link-modules/cart-links.spec.ts | 50 ++++++- .../admin/create-product-variant.spec.ts | 10 +- .../modules/__tests__/services/product.ts | 139 ------------------ integration-tests/modules/medusa-config.js | 1 + .../definitions/cart-payment-collection.ts | 61 ++++++++ .../link-modules/src/definitions/index.ts | 1 + packages/link-modules/src/links.ts | 6 + .../src/migrations/Migration20240225134525.ts | 9 +- 8 files changed, 129 insertions(+), 148 deletions(-) delete mode 100644 integration-tests/modules/__tests__/services/product.ts create mode 100644 packages/link-modules/src/definitions/cart-payment-collection.ts diff --git a/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts b/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts index 8f9e283566..84281a7452 100644 --- a/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts +++ b/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts @@ -1,7 +1,8 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk" import { ICartModuleService, ICustomerModuleService, + IPaymentModuleService, IRegionModuleService, ISalesChannelModuleService, } from "@medusajs/types" @@ -22,7 +23,8 @@ describe("Cart links", () => { let regionModule: IRegionModuleService let customerModule: ICustomerModuleService let scModuleService: ISalesChannelModuleService - let remoteQuery + let paymentModuleService: IPaymentModuleService + let remoteQuery, remoteLink beforeAll(async () => { const cwd = path.resolve(path.join(__dirname, "..", "..")) @@ -34,7 +36,9 @@ describe("Cart links", () => { customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + paymentModuleService = appContainer.resolve(ModuleRegistrationName.PAYMENT) remoteQuery = appContainer.resolve("remoteQuery") + remoteLink = appContainer.resolve("remoteLink") }) afterAll(async () => { @@ -75,6 +79,24 @@ describe("Cart links", () => { customer_id: customer.id, }) + const paymentCollection = + await paymentModuleService.createPaymentCollections({ + currency_code: "usd", + region_id: region.id, + amount: 1000, + }) + + await remoteLink.create([ + { + [Modules.CART]: { + cart_id: cart.id, + }, + [Modules.PAYMENT]: { + payment_collection_id: paymentCollection.id, + }, + }, + ]) + const carts = await remoteQuery({ cart: { fields: ["id"], @@ -87,6 +109,9 @@ describe("Cart links", () => { sales_channel: { fields: ["id"], }, + payment_collection: { + fields: ["id"], + }, }, }) @@ -117,6 +142,15 @@ describe("Cart links", () => { }, }) + const paymentCollections = await remoteQuery({ + payment: { + fields: ["id"], + cart: { + fields: ["id"], + }, + }, + }) + expect(carts).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -124,6 +158,9 @@ describe("Cart links", () => { customer: expect.objectContaining({ id: customer.id }), sales_channel: expect.objectContaining({ id: salesChannel.id }), region: expect.objectContaining({ id: region.id }), + payment_collection: expect.objectContaining({ + id: paymentCollection.id, + }), }), ]) ) @@ -160,5 +197,14 @@ describe("Cart links", () => { }), ]) ) + + expect(paymentCollections).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: paymentCollection.id, + cart: expect.objectContaining({ id: cart.id }), + }), + ]) + ) }) }) diff --git a/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts b/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts index 3fd7165c48..d26859faad 100644 --- a/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts @@ -1,3 +1,8 @@ +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 { useApi } from "../../../../environment-helpers/use-api" import { getContainer } from "../../../../environment-helpers/use-container" import { initDb, useDb } from "../../../../environment-helpers/use-db" @@ -5,13 +10,8 @@ import { simpleProductFactory, simpleRegionFactory, } 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 { ProductModuleService } from "@medusajs/product" -import { PricingModuleService } from "@medusajs/pricing" jest.setTimeout(50000) diff --git a/integration-tests/modules/__tests__/services/product.ts b/integration-tests/modules/__tests__/services/product.ts deleted file mode 100644 index c42a531941..0000000000 --- a/integration-tests/modules/__tests__/services/product.ts +++ /dev/null @@ -1,139 +0,0 @@ -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" - -jest.setTimeout(30000) - -describe("product", () => { - let medusaContainer - let productService - - let shutdownServer - - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - await initDb({ cwd }) - shutdownServer = shutdownServer = await startBootstrapApp({ cwd }) - medusaContainer = getContainer() - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - jest.clearAllMocks() - const db = useDb() - await db.teardown() - }) - - describe("product service", () => { - it("should create variant prices correctly in service creation", async () => { - productService = medusaContainer.resolve("productService") - - const payload = { - title: "test-product", - handle: "test-product", - options: [{ title: "test-option" }], - variants: [ - { - title: "test-variant", - inventory_quantity: 10, - sku: "test", - options: [{ value: "large", title: "test-option" }], - prices: [{ amount: "100", currency_code: "usd" }], - }, - ], - } - - const { id } = await productService.create(payload) - - const result = await productService.retrieve(id, { - relations: ["variants", "variants.prices", "variants.options"], - }) - - expect(result).toEqual( - expect.objectContaining({ - variants: [ - expect.objectContaining({ - options: [expect.objectContaining({ value: "large" })], - prices: [ - expect.objectContaining({ amount: 100, currency_code: "usd" }), - ], - }), - ], - }) - ) - }) - - it("should fail to create a variant without options on for a product with options", async () => { - const payload = { - title: "test-product", - handle: "test-product", - options: [{ title: "test-option" }], - variants: [ - { - title: "test-variant", - inventory_quantity: 10, - sku: "test", - prices: [{ amount: "100", currency_code: "usd" }], - }, - ], - } - - let error - - try { - await productService.create(payload) - } catch (err) { - error = err - } - - expect(error.message).toEqual( - "Product options length does not match variant options length. Product has 1 and variant has 0." - ) - }) - - it("should create a product and variant without options", async () => { - const payload = { - title: "test-product", - handle: "test-product", - variants: [ - { - title: "test-variant", - inventory_quantity: 10, - sku: "test", - prices: [{ amount: "100", currency_code: "usd" }], - }, - ], - } - - const { id } = await productService.create(payload) - - const result = await productService.retrieve(id, { - relations: [ - "options", - "variants", - "variants.prices", - "variants.options", - ], - }) - - expect(result).toEqual( - expect.objectContaining({ - options: [], - variants: [ - expect.objectContaining({ - prices: [ - expect.objectContaining({ amount: 100, currency_code: "usd" }), - ], - }), - ], - }) - ) - }) - }) -}) diff --git a/integration-tests/modules/medusa-config.js b/integration-tests/modules/medusa-config.js index 5ca9dc8519..e0d5289d41 100644 --- a/integration-tests/modules/medusa-config.js +++ b/integration-tests/modules/medusa-config.js @@ -62,5 +62,6 @@ module.exports = { [Modules.STORE]: true, [Modules.TAX]: true, [Modules.CURRENCY]: true, + [Modules.PAYMENT]: true, }, } diff --git a/packages/link-modules/src/definitions/cart-payment-collection.ts b/packages/link-modules/src/definitions/cart-payment-collection.ts new file mode 100644 index 0000000000..f07e6da6b4 --- /dev/null +++ b/packages/link-modules/src/definitions/cart-payment-collection.ts @@ -0,0 +1,61 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleJoinerConfig } from "@medusajs/types" +import { LINKS } from "../links" + +export const CartPaymentCollection: ModuleJoinerConfig = { + serviceName: LINKS.CartPaymentCollection, + isLink: true, + databaseConfig: { + tableName: "cart_payment_collection", + idPrefix: "capaycol", + }, + alias: [ + { + name: ["cart_payment_collection", "cart_payment_collections"], + args: { + entity: "LinkCartPaymentCollection", + }, + }, + ], + primaryKeys: ["id", "cart_id", "payment_collection_id"], + relationships: [ + { + serviceName: Modules.CART, + primaryKey: "id", + foreignKey: "cart_id", + alias: "cart", + }, + { + serviceName: Modules.PAYMENT, + primaryKey: "id", + foreignKey: "payment_collection_id", + alias: "payment_collection", + }, + ], + extends: [ + { + serviceName: Modules.CART, + fieldAlias: { + payment_collection: "payment_collection_link.payment_collection", + }, + relationship: { + serviceName: LINKS.CartPaymentCollection, + primaryKey: "cart_id", + foreignKey: "id", + alias: "payment_collection_link", + }, + }, + { + serviceName: Modules.PAYMENT, + fieldAlias: { + cart: "cart_link.cart", + }, + relationship: { + serviceName: LINKS.CartPaymentCollection, + primaryKey: "payment_collection_id", + foreignKey: "id", + alias: "cart_link", + }, + }, + ], +} diff --git a/packages/link-modules/src/definitions/index.ts b/packages/link-modules/src/definitions/index.ts index bc9f1e53aa..041a999960 100644 --- a/packages/link-modules/src/definitions/index.ts +++ b/packages/link-modules/src/definitions/index.ts @@ -1,4 +1,5 @@ export * from "./cart-customer" +export * from "./cart-payment-collection" export * from "./cart-region" export * from "./cart-sales-channel" export * from "./inventory-level-stock-location" diff --git a/packages/link-modules/src/links.ts b/packages/link-modules/src/links.ts index 4652a9290a..acf2efc8b4 100644 --- a/packages/link-modules/src/links.ts +++ b/packages/link-modules/src/links.ts @@ -14,6 +14,12 @@ export const LINKS = { Modules.PRICING, "price_set_id" ), + CartPaymentCollection: composeLinkName( + Modules.CART, + "cart_id", + Modules.PAYMENT, + "payment_collection_id" + ), // Internal services ProductShippingProfile: composeLinkName( diff --git a/packages/payment/src/migrations/Migration20240225134525.ts b/packages/payment/src/migrations/Migration20240225134525.ts index a1188435c9..e91ce8afba 100644 --- a/packages/payment/src/migrations/Migration20240225134525.ts +++ b/packages/payment/src/migrations/Migration20240225134525.ts @@ -17,21 +17,23 @@ export class Migration20240225134525 extends Migration { ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "completed_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL; + ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "payment_provider" ADD COLUMN IF NOT EXISTS "is_enabled" BOOLEAN NOT NULL DEFAULT TRUE; ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "payment_collection_id" TEXT NOT NULL; ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "payment_authorized_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL; + ALTER TABLE IF EXISTS "payment_session" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "payment_collection_id" TEXT NOT NULL; ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "provider_id" TEXT NOT NULL; ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL; - - ALTER TABLE IF EXISTS "capture" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL; + ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL; ALTER TABLE IF EXISTS "refund" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL; + ALTER TABLE IF EXISTS "refund" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL; CREATE TABLE IF NOT EXISTS "capture" ( "id" TEXT NOT NULL, @@ -39,7 +41,10 @@ export class Migration20240225134525 extends Migration { "raw_amount" JSONB NOT NULL, "payment_id" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(), + "deleted_at" TIMESTAMPTZ NULL, "created_by" TEXT NULL, + "metadata" JSONB NULL, CONSTRAINT "capture_pkey" PRIMARY KEY ("id") );