From b3093c3e3d64e4c024a04d76fb0f727c1c38108b Mon Sep 17 00:00:00 2001 From: Bastien Date: Thu, 16 Nov 2023 20:37:02 +0100 Subject: [PATCH] feat(medusa): Add `metadata` to Product Category (#5599) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(migrations): add metadata column to product_category table in database to store additional information about each product category * ✨ feat(product-category.ts): add metadata field to ProductCategory model to store additional details 📝 docs(product-category.ts): add documentation for new metadata field in ProductCategory model * ✨ feat(product-category.ts): add metadata field to ProductCategoryInput type to support additional data * ✨ feat(ProductCategory.ts): add optional metadata field to ProductCategory model to store additional details * ✨ feat(product-categories): add metadata field to product categories for additional information storage 📝 docs(product-categories): add documentation for new metadata field in product categories * ✨ feat(product-categories): add 'metadata' field to default and allowed product category fields for enhanced data tracking * ✨ feat(product-category.ts): add metadata support to product categories 🔧 refactor(product-category.ts): import setMetadata from utils to handle metadata setting in a more efficient way * ✨ feat(models): add metadata field to AdminPostProductCategoriesCategoryReq and AdminPostProductCategoriesReq models to store additional information * 📝 docs(api-reference): add metadata field to ProductCategory schema in both admin and store specs 🔧 fix(api-reference): make metadata field required in ProductCategory schema to ensure data consistency * Create nine-fishes-matter.md --------- Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> --- .changeset/nine-fishes-matter.md | 6 ++++++ .../AdminPostProductCategoriesCategoryReq.ts | 4 ++++ .../models/AdminPostProductCategoriesReq.ts | 4 ++++ .../src/lib/models/ProductCategory.ts | 4 ++++ .../create-product-category.ts | 12 +++++++++++- .../routes/admin/product-categories/index.ts | 1 + .../update-product-category.ts | 19 ++++++++++++++++++- .../routes/store/product-categories/index.ts | 2 ++ ...794649-add-metadata-to-product-category.ts | 17 +++++++++++++++++ .../medusa/src/models/product-category.ts | 13 +++++++++++++ .../medusa/src/services/product-category.ts | 8 +++++++- packages/medusa/src/types/product-category.ts | 1 + .../components/schemas/ProductCategory.yaml | 11 +++++++++++ .../components/schemas/ProductCategory.yaml | 11 +++++++++++ 14 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 .changeset/nine-fishes-matter.md create mode 100644 packages/medusa/src/migrations/1699564794649-add-metadata-to-product-category.ts diff --git a/.changeset/nine-fishes-matter.md b/.changeset/nine-fishes-matter.md new file mode 100644 index 0000000000..ed9510c984 --- /dev/null +++ b/.changeset/nine-fishes-matter.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"@medusajs/client-types": patch +--- + +feat(medusa): Add `metadata` to Product Category diff --git a/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesCategoryReq.ts b/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesCategoryReq.ts index d5eedef995..1b97e3ba48 100644 --- a/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesCategoryReq.ts +++ b/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesCategoryReq.ts @@ -32,4 +32,8 @@ export interface AdminPostProductCategoriesCategoryReq { * The rank of the category in the tree node (starting from 0) */ rank?: number + /** + * An optional set of key-value pairs to hold additional information. + */ + metadata?: Record } diff --git a/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesReq.ts b/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesReq.ts index c38e72bfeb..edb17f41bf 100644 --- a/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesReq.ts +++ b/packages/generated/client-types/src/lib/models/AdminPostProductCategoriesReq.ts @@ -28,4 +28,8 @@ export interface AdminPostProductCategoriesReq { * The ID of the parent product category */ parent_category_id?: string + /** + * An optional set of key-value pairs to hold additional information. + */ + metadata?: Record } diff --git a/packages/generated/client-types/src/lib/models/ProductCategory.ts b/packages/generated/client-types/src/lib/models/ProductCategory.ts index d25d665a90..d6b0e6a33e 100644 --- a/packages/generated/client-types/src/lib/models/ProductCategory.ts +++ b/packages/generated/client-types/src/lib/models/ProductCategory.ts @@ -65,4 +65,8 @@ export interface ProductCategory { * The date with timezone at which the resource was updated. */ updated_at: string + /** + * An optional key-value map with additional details + */ + metadata: Record | null } diff --git a/packages/medusa/src/api/routes/admin/product-categories/create-product-category.ts b/packages/medusa/src/api/routes/admin/product-categories/create-product-category.ts index 4dae41d6ea..5ba8195318 100644 --- a/packages/medusa/src/api/routes/admin/product-categories/create-product-category.ts +++ b/packages/medusa/src/api/routes/admin/product-categories/create-product-category.ts @@ -1,4 +1,4 @@ -import { IsNotEmpty, IsString } from "class-validator" +import { IsNotEmpty, IsString, IsObject, IsOptional } from "class-validator" import { Request, Response } from "express" import { EntityManager } from "typeorm" @@ -122,12 +122,22 @@ export default async (req: Request, res: Response) => { * parent_category_id: * type: string * description: The ID of the parent product category + * metadata: + * description: An optional set of key-value pairs to hold additional information. + * type: object + * externalDocs: + * description: "Learn about the metadata attribute, and how to delete and update it." + * url: "https://docs.medusajs.com/development/entities/overview#metadata-attribute" */ // eslint-disable-next-line max-len export class AdminPostProductCategoriesReq extends AdminProductCategoriesReqBase { @IsString() @IsNotEmpty() name: string + + @IsObject() + @IsOptional() + metadata?: Record } export class AdminPostProductCategoriesParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/product-categories/index.ts b/packages/medusa/src/api/routes/admin/product-categories/index.ts index cb86923f59..dca28132e8 100644 --- a/packages/medusa/src/api/routes/admin/product-categories/index.ts +++ b/packages/medusa/src/api/routes/admin/product-categories/index.ts @@ -149,6 +149,7 @@ export const defaultProductCategoryFields = [ "parent_category_id", "created_at", "updated_at", + "metadata", ] /** diff --git a/packages/medusa/src/api/routes/admin/product-categories/update-product-category.ts b/packages/medusa/src/api/routes/admin/product-categories/update-product-category.ts index 69ca797df9..f8e5e0da08 100644 --- a/packages/medusa/src/api/routes/admin/product-categories/update-product-category.ts +++ b/packages/medusa/src/api/routes/admin/product-categories/update-product-category.ts @@ -1,4 +1,11 @@ -import { IsOptional, IsString, IsInt, Min, IsNotEmpty } from "class-validator" +import { + IsOptional, + IsString, + IsInt, + Min, + IsNotEmpty, + IsObject, +} from "class-validator" import { Request, Response } from "express" import { EntityManager } from "typeorm" @@ -123,6 +130,12 @@ export default async (req: Request, res: Response) => { * rank: * type: number * description: The rank of the category in the tree node (starting from 0) + * metadata: + * description: An optional set of key-value pairs to hold additional information. + * type: object + * externalDocs: + * description: "Learn about the metadata attribute, and how to delete and update it." + * url: "https://docs.medusajs.com/development/entities/overview#metadata-attribute" */ // eslint-disable-next-line max-len export class AdminPostProductCategoriesCategoryReq extends AdminProductCategoriesReqBase { @@ -140,6 +153,10 @@ export class AdminPostProductCategoriesCategoryReq extends AdminProductCategorie @IsNotEmpty() @Min(0) rank?: number + + @IsObject() + @IsOptional() + metadata?: Record } export class AdminPostProductCategoriesCategoryParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/store/product-categories/index.ts b/packages/medusa/src/api/routes/store/product-categories/index.ts index 200d367623..5ae0920e34 100644 --- a/packages/medusa/src/api/routes/store/product-categories/index.ts +++ b/packages/medusa/src/api/routes/store/product-categories/index.ts @@ -60,6 +60,7 @@ export const defaultStoreProductCategoryFields = [ "created_at", "updated_at", "rank", + "metadata", ] export const allowedStoreProductCategoryFields = [ @@ -71,6 +72,7 @@ export const allowedStoreProductCategoryFields = [ "created_at", "updated_at", "rank", + "metadata", ] /** diff --git a/packages/medusa/src/migrations/1699564794649-add-metadata-to-product-category.ts b/packages/medusa/src/migrations/1699564794649-add-metadata-to-product-category.ts new file mode 100644 index 0000000000..8205f36910 --- /dev/null +++ b/packages/medusa/src/migrations/1699564794649-add-metadata-to-product-category.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class AddMetadataToProductCategory1699564794649 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "product_category" ADD COLUMN "metadata" jsonb NULL;` + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "product_category" DROP COLUMN "metadata"` + ) + } + +} diff --git a/packages/medusa/src/models/product-category.ts b/packages/medusa/src/models/product-category.ts index 2dee6af5cc..7e4a878e5a 100644 --- a/packages/medusa/src/models/product-category.ts +++ b/packages/medusa/src/models/product-category.ts @@ -1,6 +1,7 @@ import { generateEntityId } from "../utils/generate-entity-id" import { BaseEntity } from "../interfaces/models/base-entity" import { kebabCase } from "lodash" +import { DbAwareColumn } from "../utils/db-aware-column" import { Product } from "." import { BeforeInsert, @@ -64,6 +65,9 @@ export class ProductCategory extends BaseEntity { @Column({ nullable: false, default: 0 }) rank: number + @DbAwareColumn({ type: "jsonb", nullable: true }) + metadata: Record + @ManyToMany(() => Product, { cascade: ["remove", "soft-remove"] }) @JoinTable({ name: ProductCategory.productCategoryProductJoinTable, @@ -105,6 +109,7 @@ export class ProductCategory extends BaseEntity { * - id * - is_active * - is_internal + * - metadata * - mpath * - name * - parent_category_id @@ -173,4 +178,12 @@ export class ProductCategory extends BaseEntity { * description: The date with timezone at which the resource was updated. * type: string * format: date-time + * metadata: + * description: An optional key-value map with additional details + * nullable: true + * type: object + * example: {car: "white"} + * externalDocs: + * description: "Learn about the metadata attribute, and how to delete and update it." + * url: "https://docs.medusajs.com/development/entities/overview#metadata-attribute" */ diff --git a/packages/medusa/src/services/product-category.ts b/packages/medusa/src/services/product-category.ts index e2ccc12db4..36e74db301 100644 --- a/packages/medusa/src/services/product-category.ts +++ b/packages/medusa/src/services/product-category.ts @@ -16,7 +16,7 @@ import { tempReorderRank, UpdateProductCategoryInput, } from "../types/product-category" -import { buildQuery, nullableValue } from "../utils" +import { buildQuery, nullableValue, setMetadata } from "../utils" type InjectedDependencies = { manager: EntityManager @@ -229,6 +229,12 @@ class ProductCategoryService extends TransactionBaseService { this.productCategoryRepo_ ) + const { metadata, ...rest } = productCategoryInput + + if (metadata) { + productCategory.metadata = setMetadata(productCategory, metadata) + } + const conditions = this.fetchReorderConditions( productCategory, productCategoryInput diff --git a/packages/medusa/src/types/product-category.ts b/packages/medusa/src/types/product-category.ts index 156cde0f84..60a9ca9b36 100644 --- a/packages/medusa/src/types/product-category.ts +++ b/packages/medusa/src/types/product-category.ts @@ -17,6 +17,7 @@ type ProductCategoryInput = { parent_category_id?: string | null parent_category?: ProductCategory | null rank?: number + metadata?: Record } export type CreateProductCategoryInput = ProductCategoryInput & { diff --git a/www/apps/api-reference/specs/admin/components/schemas/ProductCategory.yaml b/www/apps/api-reference/specs/admin/components/schemas/ProductCategory.yaml index e49782d700..2a9d4d63a0 100644 --- a/www/apps/api-reference/specs/admin/components/schemas/ProductCategory.yaml +++ b/www/apps/api-reference/specs/admin/components/schemas/ProductCategory.yaml @@ -12,6 +12,7 @@ required: - id - is_active - is_internal + - metadata - mpath - name - parent_category_id @@ -84,3 +85,13 @@ properties: description: The date with timezone at which the resource was updated. type: string format: date-time + metadata: + description: An optional key-value map with additional details + nullable: true + type: object + example: + car: white + externalDocs: + description: Learn about the metadata attribute, and how to delete and update it. + url: >- + https://docs.medusajs.com/development/entities/overview#metadata-attribute diff --git a/www/apps/api-reference/specs/store/components/schemas/ProductCategory.yaml b/www/apps/api-reference/specs/store/components/schemas/ProductCategory.yaml index e49782d700..2a9d4d63a0 100644 --- a/www/apps/api-reference/specs/store/components/schemas/ProductCategory.yaml +++ b/www/apps/api-reference/specs/store/components/schemas/ProductCategory.yaml @@ -12,6 +12,7 @@ required: - id - is_active - is_internal + - metadata - mpath - name - parent_category_id @@ -84,3 +85,13 @@ properties: description: The date with timezone at which the resource was updated. type: string format: date-time + metadata: + description: An optional key-value map with additional details + nullable: true + type: object + example: + car: white + externalDocs: + description: Learn about the metadata attribute, and how to delete and update it. + url: >- + https://docs.medusajs.com/development/entities/overview#metadata-attribute