feat(product): Create (+ workflow), delete, restore (#4459)
* Feat: create product with product module * feat: create product wip * feat: create product wip * feat: update product relation and generate image migration * lint * conitnue implementation * continue implementation and add integration tests for produceService.create * Add integration tests for product creation at the module level for the complete flow * only use persist since write operations are always wrapped in a transaction which will be committed and flushed * simplify the transaction wrapper to make future changes easier * feat: move some utils to the utils package to simplify its usage * tests: fix unit tests * feat: create variants along side the product * Add more integration tests an update migrations * chore: Update actions workflow to include packages integration tests * small types and utils cleanup * chore: Add support for database debug option * chore: Add missing types in package.json from types and util, validate that all the models are sync with medusa * expose retrieve method * fix types issues * fix unit tests and move integration tests workflow with the plugins integration tests * chore: remove migration function export from the definition to prevent them to be ran by the medusa cli just in case * fix package.json script * chore: workflows * feat: start creating the create product workflow * feat: add empty step for prices and sales channel * tests: update scripts and action envs * fix imports * feat: Add proper soft deleted support + add product deletion service public api * chore: update migrations * chore: update migrations * chore: update todo * feat: Add product deletion to the create-product workflow as compensation * chore: cleanup product utils * feat: Add support for cascade soft-remove * feat: refactor repository to take into account withDeleted * fix integration tests * Add support for force delete -> delete, cleanup repositories and improvements * Add support for restoring a product and add integration tests * cleaup + tests * types * fix integration tests * remove unnecessary comments * move specific mikro orm usage to the DAL * Cleanup workflow functions * Make deleted_at optional at the property level and add url index for the images * address feedback + cleanup * fix export * merge migrations into one * feat(product, types): added missing product variant methods (#4475) * chore: added missing product variant methods * chore: address PR feedback * chore: catch undefined case for retrieve + specs for variant service * chore: align TEntity + add changeset * chore: revert changeset, TEntity to ProductVariant * chore: write tests for pagination, unskip the test * Create chilled-mice-deliver.md * update integration fixtuers * update pipeline node version * rename github action * fix pipeline * feat(medusa, types): added missing category tests and service methods (#4499) * chore: added missing category tests and service methods * chore: added type changes to module service * chore: address pr feedback * update repositories manager usage and serialisation from the write public API * move serializisation to the DAL * rename template args * chore: added collection methods for module and collection service (#4505) * chore: added collection methods for module and collection service * Create fresh-islands-teach.md * chore: move retrieve entity to utils package * chore: make products optional in DTO type --------- Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> * feat(product): Apply transaction decorators to the services (#4512) --------- Co-authored-by: Riqwan Thamir <rmthamir@gmail.com> Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
co-authored by
Oliver Windall Juhl
Riqwan Thamir
Carlos R. L. Rodrigues
parent
5b91a3503a
commit
befc2f1c80
@@ -1,14 +1,9 @@
|
||||
import { FindOptions, RepositoryService } from "@medusajs/types"
|
||||
import { BaseRepository } from "../../src/repositories/base"
|
||||
|
||||
class CustomRepository implements RepositoryService {
|
||||
constructor() {}
|
||||
|
||||
find(options?: FindOptions): Promise<any[]> {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
findAndCount(options?: FindOptions): Promise<[any[], number]> {
|
||||
throw new Error("Method not implemented.")
|
||||
class CustomRepository extends BaseRepository {
|
||||
constructor({ manager }) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
import faker from "faker"
|
||||
import { Image } from "@models"
|
||||
|
||||
export const buildProductOnlyData = ({
|
||||
title,
|
||||
description,
|
||||
subtitle,
|
||||
is_giftcard,
|
||||
discountable,
|
||||
thumbnail,
|
||||
images,
|
||||
status,
|
||||
}: {
|
||||
title?: string
|
||||
description?: string
|
||||
subtitle?: string
|
||||
is_giftcard?: boolean
|
||||
discountable?: boolean
|
||||
thumbnail?: string
|
||||
images?: { id?: string; url: string }[]
|
||||
status?: ProductTypes.ProductStatus
|
||||
} = {}) => {
|
||||
return {
|
||||
title: title ?? faker.commerce.productName(),
|
||||
description: description ?? faker.commerce.productName(),
|
||||
subtitle: subtitle ?? faker.commerce.productName(),
|
||||
is_giftcard: is_giftcard ?? false,
|
||||
discountable: discountable ?? true,
|
||||
thumbnail: thumbnail as string,
|
||||
status: status ?? ProductTypes.ProductStatus.PUBLISHED,
|
||||
images: (images ?? []) as Image[],
|
||||
}
|
||||
}
|
||||
|
||||
export const buildProductAndRelationsData = ({
|
||||
title,
|
||||
description,
|
||||
subtitle,
|
||||
is_giftcard,
|
||||
discountable,
|
||||
thumbnail,
|
||||
images,
|
||||
status,
|
||||
type,
|
||||
tags,
|
||||
options,
|
||||
variants,
|
||||
}: Partial<ProductTypes.CreateProductDTO>) => {
|
||||
const defaultOptionTitle = faker.commerce.productName()
|
||||
return {
|
||||
title: title ?? faker.commerce.productName(),
|
||||
description: description ?? faker.commerce.productName(),
|
||||
subtitle: subtitle ?? faker.commerce.productName(),
|
||||
is_giftcard: is_giftcard ?? false,
|
||||
discountable: discountable ?? true,
|
||||
thumbnail: thumbnail as string,
|
||||
status: status ?? ProductTypes.ProductStatus.PUBLISHED,
|
||||
images: (images ?? []) as Image[],
|
||||
type: type ? { value: type } : { value: faker.commerce.productName() },
|
||||
tags: tags ?? [{ value: "tag-1" }],
|
||||
options: options ?? [
|
||||
{
|
||||
title: defaultOptionTitle,
|
||||
},
|
||||
],
|
||||
variants: variants ?? [
|
||||
{
|
||||
title: faker.commerce.productName(),
|
||||
sku: faker.commerce.productName(),
|
||||
options: [
|
||||
{
|
||||
value: defaultOptionTitle + faker.commerce.productName(),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
// TODO: add categories, must be created first
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import {
|
||||
Image,
|
||||
Product,
|
||||
ProductCategory,
|
||||
ProductCollection,
|
||||
@@ -7,9 +9,16 @@ import {
|
||||
} from "@models"
|
||||
import ProductOption from "../../../src/models/product-option"
|
||||
|
||||
export * from "./data/create-product"
|
||||
|
||||
export async function createProductAndTags(
|
||||
manager: SqlEntityManager,
|
||||
data: any[]
|
||||
data: {
|
||||
id?: string
|
||||
title: string
|
||||
status: ProductTypes.ProductStatus
|
||||
tags?: { id: string; value: string }[]
|
||||
}[]
|
||||
) {
|
||||
const products: any[] = data.map((productData) => {
|
||||
return manager.create(Product, productData)
|
||||
@@ -35,7 +44,11 @@ export async function createProductVariants(
|
||||
|
||||
export async function createCollections(
|
||||
manager: SqlEntityManager,
|
||||
collectionData: any[]
|
||||
collectionData: {
|
||||
id?: string
|
||||
title: string
|
||||
handle?: string
|
||||
}[]
|
||||
) {
|
||||
const collections: any[] = collectionData.map((collectionData) => {
|
||||
return manager.create(ProductCollection, collectionData)
|
||||
@@ -48,10 +61,21 @@ export async function createCollections(
|
||||
|
||||
export async function createOptions(
|
||||
manager: SqlEntityManager,
|
||||
optionsData: any[]
|
||||
optionsData: {
|
||||
id?: string
|
||||
product: { id: string }
|
||||
title: string
|
||||
value?: string
|
||||
values?: {
|
||||
id?: string
|
||||
value: string
|
||||
variant?: { id: string } & any
|
||||
}[]
|
||||
variant?: { id: string } & any
|
||||
}[]
|
||||
) {
|
||||
const options: any[] = optionsData.map((o) => {
|
||||
return manager.create(ProductOption, o)
|
||||
const options: any[] = optionsData.map((option) => {
|
||||
return manager.create(ProductOption, option)
|
||||
})
|
||||
|
||||
await manager.persistAndFlush(options)
|
||||
@@ -59,6 +83,19 @@ export async function createOptions(
|
||||
return options
|
||||
}
|
||||
|
||||
export async function createImages(
|
||||
manager: SqlEntityManager,
|
||||
imagesData: string[]
|
||||
) {
|
||||
const images: any[] = imagesData.map((img) => {
|
||||
return manager.create(Image, { url: img })
|
||||
})
|
||||
|
||||
await manager.persistAndFlush(images)
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
export async function assignCategoriesToProduct(
|
||||
manager: SqlEntityManager,
|
||||
product: Product,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { ProductTypes } from "@medusajs/types"
|
||||
import faker from "faker"
|
||||
|
||||
export const buildProductVariantOnlyData = ({
|
||||
title,
|
||||
sku,
|
||||
barcode,
|
||||
ean,
|
||||
upc,
|
||||
allow_backorder,
|
||||
inventory_quantity,
|
||||
manage_inventory,
|
||||
hs_code,
|
||||
origin_country,
|
||||
mid_code,
|
||||
material,
|
||||
weight,
|
||||
length,
|
||||
height,
|
||||
width,
|
||||
options,
|
||||
metadata,
|
||||
}: Partial<ProductTypes.CreateProductVariantOnlyDTO>) => {
|
||||
return {
|
||||
title: title ?? faker.commerce.productName(),
|
||||
sku: sku ?? faker.commerce.productName(),
|
||||
barcode,
|
||||
ean,
|
||||
upc,
|
||||
allow_backorder,
|
||||
inventory_quantity,
|
||||
manage_inventory,
|
||||
hs_code,
|
||||
origin_country,
|
||||
mid_code,
|
||||
material,
|
||||
weight,
|
||||
length,
|
||||
height,
|
||||
width,
|
||||
options,
|
||||
metadata,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./data/create-variant"
|
||||
Reference in New Issue
Block a user