Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(medusa): variant creation with prices in productservice.create #5410

Merged
merged 40 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1c47273
ensure vairant creation in product endpoint works + integration test
pKorsholm Oct 18, 2023
4c39e05
add expect statement for test
pKorsholm Oct 18, 2023
c0299d4
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 18, 2023
d8d03e6
update unit tests
pKorsholm Oct 18, 2023
d10e61e
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 18, 2023
e325597
update tests
pKorsholm Oct 19, 2023
854899c
add more test
pKorsholm Oct 19, 2023
7176fa9
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 19, 2023
230045d
fix unit tests
pKorsholm Oct 19, 2023
3ad2dcb
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 19, 2023
f0b3c13
Create small-eggs-search.md
olivermrbl Oct 19, 2023
0fc679e
Merge branch 'develop' into fix/variant-creation-in-create-product
olivermrbl Oct 19, 2023
c8544eb
revert config change
pKorsholm Oct 19, 2023
cf221b4
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 19, 2023
84034d4
make separate services integration test suite
pKorsholm Oct 19, 2023
8568216
remove only
pKorsholm Oct 19, 2023
4d33e81
rename step
pKorsholm Oct 19, 2023
9802fc1
update jest config
pKorsholm Oct 19, 2023
074ddd8
add database_extras
pKorsholm Oct 19, 2023
6f401cd
update config
pKorsholm Oct 19, 2023
e5999ca
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 19, 2023
22527f6
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 20, 2023
4017b57
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 20, 2023
0d5f92f
add build step
pKorsholm Oct 20, 2023
efd7962
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 23, 2023
e77ad65
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 23, 2023
22a50f1
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 26, 2023
7813e5e
proper beforeAll
pKorsholm Oct 26, 2023
5c0199b
add console log
pKorsholm Oct 26, 2023
7e9cc61
more logs
pKorsholm Oct 26, 2023
8d18d82
add build step for specific tests
pKorsholm Oct 26, 2023
cf2be4e
fe:tch depth 1
pKorsholm Oct 26, 2023
2119125
wrap in describe
pKorsholm Oct 26, 2023
de784eb
update medusaconfig
pKorsholm Oct 26, 2023
f8f1184
Merge branch 'develop' into fix/variant-creation-in-create-product
pKorsholm Oct 26, 2023
3db7f4d
update medusaconfig
pKorsholm Oct 26, 2023
d501f04
retry integration config
pKorsholm Oct 26, 2023
02813f6
remove services test-suite
pKorsholm Oct 26, 2023
0d40fc2
undo changes
pKorsholm Oct 26, 2023
5c5790e
rename integration test file
pKorsholm Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/small-eggs-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---

feat(medusa): variant creation with prices in productservice.create
147 changes: 147 additions & 0 deletions integration-tests/plugins/__tests__/services/product.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import path from "path"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment(this-file): Something is off about having integration tests for core services in the plugins directory. I think we should move this to API (even though not ideal either) to have it closer to the core. Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, however there's something about having the redis_url in the project config of the api that breaks the bootstrapApp({ cwd }) method for server setup, though it's needed to get the container

import { initDb, useDb } from "../../../environment-helpers/use-db"
import { bootstrapApp } from "../../../environment-helpers/bootstrap-app"
import { setPort } from "../../../environment-helpers/use-api"

jest.setTimeout(30000)

describe("product", () => {
let dbConnection
let medusaContainer
let productService

let express

beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."))
dbConnection = await initDb({ cwd } as any)
const { container, port, app } = await bootstrapApp({ cwd })

setPort(port)
express = app.listen(port, () => {
process.send!(port)
})

medusaContainer = container
})

afterAll(async () => {
const db = useDb()
await db.shutdown()

express.close()
})

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" }),
],
}),
],
})
)
})
})
})
24 changes: 12 additions & 12 deletions packages/medusa/src/services/__tests__/product.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("ProductService", () => {
title: "Suit",
options: [],
collection: { id: IdMap.getId("cat"), title: "Suits" },
variants: product.variants,
variants: product.variants ?? [],
}),
findOneWithRelations: () => ({
id: IdMap.getId("ironman"),
Expand Down Expand Up @@ -117,21 +117,29 @@ describe("ProductService", () => {
Promise.resolve({ id: IdMap.getId("cat"), title: "Suits" }),
}

const productVariantService = {
withTransaction: function () {
return this
},
create: (id, data) => Promise.resolve(data),
}

const productService = new ProductService({
manager: MockManager,
productRepository,
eventBusService,
productCollectionService,
productTagRepository,
productTypeRepository,
productVariantService,
featureFlagRouter: new FlagRouter({}),
})

beforeEach(() => {
jest.clearAllMocks()
})

it("successfully create a product", async () => {
it("should successfully create a product", async () => {
await productService.create({
title: "Suit",
options: [],
Expand All @@ -158,16 +166,6 @@ describe("ProductService", () => {
expect(productRepository.create).toHaveBeenCalledTimes(1)
expect(productRepository.create).toHaveBeenCalledWith({
title: "Suit",
variants: [
{
id: "test1",
title: "green",
},
{
id: "test2",
title: "blue",
},
],
})

expect(productTagRepository.upsertTags).toHaveBeenCalledTimes(1)
Expand Down Expand Up @@ -197,10 +195,12 @@ describe("ProductService", () => {
variants: [
{
id: "test1",
options: [],
title: "green",
},
{
id: "test2",
options: [],
title: "blue",
},
],
Expand Down
61 changes: 43 additions & 18 deletions packages/medusa/src/services/product.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import {
buildRelations,
buildSelects, FlagRouter, objectToStringPath
buildRelations,
buildSelects,
FlagRouter,
objectToStringPath,
} from "@medusajs/utils"
import { isDefined, MedusaError } from "medusa-core-utils"
import { EntityManager, In } from "typeorm"
import { ProductVariantService, SearchService } from "."
import { TransactionBaseService } from "../interfaces"
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
import {
Product,
ProductCategory,
ProductOption,
ProductTag,
ProductType,
ProductVariant,
SalesChannel,
ShippingProfile,
Product,
ProductCategory,
ProductOption,
ProductTag,
ProductType,
ProductVariant,
SalesChannel,
ShippingProfile,
} from "../models"
import { ImageRepository } from "../repositories/image"
import {
FindWithoutRelationsOptions,
ProductRepository,
FindWithoutRelationsOptions,
ProductRepository,
} from "../repositories/product"
import { ProductCategoryRepository } from "../repositories/product-category"
import { ProductOptionRepository } from "../repositories/product-option"
Expand All @@ -29,15 +31,16 @@ import { ProductTypeRepository } from "../repositories/product-type"
import { ProductVariantRepository } from "../repositories/product-variant"
import { Selector } from "../types/common"
import {
CreateProductInput,
FilterableProductProps,
FindProductConfig,
ProductOptionInput,
ProductSelector,
UpdateProductInput,
CreateProductInput,
FilterableProductProps,
FindProductConfig,
ProductOptionInput,
ProductSelector,
UpdateProductInput,
} from "../types/product"
import { buildQuery, isString, setMetadata } from "../utils"
import EventBusService from "./event-bus"
import { CreateProductVariantInput } from "../types/product-variant"

type InjectedDependencies = {
manager: EntityManager
Expand Down Expand Up @@ -429,6 +432,7 @@ class ProductService extends TransactionBaseService {
tags,
type,
images,
variants,
sales_channels: salesChannels,
categories: categories,
...rest
Expand Down Expand Up @@ -501,6 +505,27 @@ class ProductService extends TransactionBaseService {
})
)

if (variants) {
const toCreate = variants.map((variant) => {
pKorsholm marked this conversation as resolved.
Show resolved Hide resolved
return {
...variant,
options:
variant.options?.map((option, index) => {
return {
option_id: product.options[index].id,
...option,
}
}) ?? [],
}
})
product.variants = await this.productVariantService_
.withTransaction(manager)
.create(
product.id,
toCreate as unknown as CreateProductVariantInput[]
)
}

const result = await this.retrieve(product.id, {
relations: ["options"],
})
Expand Down