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
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk"
|
||||||
import {
|
import {
|
||||||
ICartModuleService,
|
ICartModuleService,
|
||||||
ICustomerModuleService,
|
ICustomerModuleService,
|
||||||
|
IPaymentModuleService,
|
||||||
IRegionModuleService,
|
IRegionModuleService,
|
||||||
ISalesChannelModuleService,
|
ISalesChannelModuleService,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
@@ -22,7 +23,8 @@ describe("Cart links", () => {
|
|||||||
let regionModule: IRegionModuleService
|
let regionModule: IRegionModuleService
|
||||||
let customerModule: ICustomerModuleService
|
let customerModule: ICustomerModuleService
|
||||||
let scModuleService: ISalesChannelModuleService
|
let scModuleService: ISalesChannelModuleService
|
||||||
let remoteQuery
|
let paymentModuleService: IPaymentModuleService
|
||||||
|
let remoteQuery, remoteLink
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
@@ -34,7 +36,9 @@ describe("Cart links", () => {
|
|||||||
customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER)
|
customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER)
|
||||||
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||||
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||||
|
paymentModuleService = appContainer.resolve(ModuleRegistrationName.PAYMENT)
|
||||||
remoteQuery = appContainer.resolve("remoteQuery")
|
remoteQuery = appContainer.resolve("remoteQuery")
|
||||||
|
remoteLink = appContainer.resolve("remoteLink")
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@@ -75,6 +79,24 @@ describe("Cart links", () => {
|
|||||||
customer_id: customer.id,
|
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({
|
const carts = await remoteQuery({
|
||||||
cart: {
|
cart: {
|
||||||
fields: ["id"],
|
fields: ["id"],
|
||||||
@@ -87,6 +109,9 @@ describe("Cart links", () => {
|
|||||||
sales_channel: {
|
sales_channel: {
|
||||||
fields: ["id"],
|
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(carts).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -124,6 +158,9 @@ describe("Cart links", () => {
|
|||||||
customer: expect.objectContaining({ id: customer.id }),
|
customer: expect.objectContaining({ id: customer.id }),
|
||||||
sales_channel: expect.objectContaining({ id: salesChannel.id }),
|
sales_channel: expect.objectContaining({ id: salesChannel.id }),
|
||||||
region: expect.objectContaining({ id: region.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 }),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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 { useApi } from "../../../../environment-helpers/use-api"
|
||||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||||
@@ -5,13 +10,8 @@ import {
|
|||||||
simpleProductFactory,
|
simpleProductFactory,
|
||||||
simpleRegionFactory,
|
simpleRegionFactory,
|
||||||
} from "../../../../factories"
|
} from "../../../../factories"
|
||||||
import { AxiosInstance } from "axios"
|
|
||||||
import path from "path"
|
|
||||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||||
import { ProductModuleService } from "@medusajs/product"
|
|
||||||
import { PricingModuleService } from "@medusajs/pricing"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
|
|||||||
@@ -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" }),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -62,5 +62,6 @@ module.exports = {
|
|||||||
[Modules.STORE]: true,
|
[Modules.STORE]: true,
|
||||||
[Modules.TAX]: true,
|
[Modules.TAX]: true,
|
||||||
[Modules.CURRENCY]: true,
|
[Modules.CURRENCY]: true,
|
||||||
|
[Modules.PAYMENT]: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./cart-customer"
|
export * from "./cart-customer"
|
||||||
|
export * from "./cart-payment-collection"
|
||||||
export * from "./cart-region"
|
export * from "./cart-region"
|
||||||
export * from "./cart-sales-channel"
|
export * from "./cart-sales-channel"
|
||||||
export * from "./inventory-level-stock-location"
|
export * from "./inventory-level-stock-location"
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ export const LINKS = {
|
|||||||
Modules.PRICING,
|
Modules.PRICING,
|
||||||
"price_set_id"
|
"price_set_id"
|
||||||
),
|
),
|
||||||
|
CartPaymentCollection: composeLinkName(
|
||||||
|
Modules.CART,
|
||||||
|
"cart_id",
|
||||||
|
Modules.PAYMENT,
|
||||||
|
"payment_collection_id"
|
||||||
|
),
|
||||||
|
|
||||||
// Internal services
|
// Internal services
|
||||||
ProductShippingProfile: composeLinkName(
|
ProductShippingProfile: composeLinkName(
|
||||||
|
|||||||
@@ -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 "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 "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_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_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 "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 "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 "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 "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 "provider_id" TEXT NOT NULL;
|
||||||
ALTER TABLE IF EXISTS "payment" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
ALTER TABLE IF EXISTS "payment" 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 "capture" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT 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 "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" (
|
CREATE TABLE IF NOT EXISTS "capture" (
|
||||||
"id" TEXT NOT NULL,
|
"id" TEXT NOT NULL,
|
||||||
@@ -39,7 +41,10 @@ export class Migration20240225134525 extends Migration {
|
|||||||
"raw_amount" JSONB NOT NULL,
|
"raw_amount" JSONB NOT NULL,
|
||||||
"payment_id" TEXT NOT NULL,
|
"payment_id" TEXT NOT NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
"created_by" TEXT NULL,
|
"created_by" TEXT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
CONSTRAINT "capture_pkey" PRIMARY KEY ("id")
|
CONSTRAINT "capture_pkey" PRIMARY KEY ("id")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user