fix(medusa): Upsert product images (#200)

This commit is contained in:
Oliver Windall Juhl authored and GitHub committed 2021-03-12 10:09:01 +01:00
1 parent 0601b34765
commit a031f1f338
5 files changed
+84 -6

No files matched your search

@@ -42,6 +42,7 @@ describe("/admin/products", () => {
const manager = dbConnection.manager; const manager = dbConnection.manager;
await manager.query(`DELETE FROM "product_option_value"`); await manager.query(`DELETE FROM "product_option_value"`);
await manager.query(`DELETE FROM "product_option"`); await manager.query(`DELETE FROM "product_option"`);
await manager.query(`DELETE FROM "image"`);
await manager.query(`DELETE FROM "money_amount"`); await manager.query(`DELETE FROM "money_amount"`);
await manager.query(`DELETE FROM "product_variant"`); await manager.query(`DELETE FROM "product_variant"`);
await manager.query(`DELETE FROM "product"`); await manager.query(`DELETE FROM "product"`);
@@ -62,6 +63,7 @@ describe("/admin/products", () => {
title: "Test product", title: "Test product",
description: "test-product-description", description: "test-product-description",
type: { value: "test-type" }, type: { value: "test-type" },
images: ["test-image.png", "test-image-2.png"],
collection_id: "test-collection", collection_id: "test-collection",
tags: [{ value: "123" }, { value: "456" }], tags: [{ value: "123" }, { value: "456" }],
options: [{ title: "size" }, { title: "color" }], options: [{ title: "size" }, { title: "color" }],
@@ -91,6 +93,15 @@ describe("/admin/products", () => {
expect.objectContaining({ expect.objectContaining({
title: "Test product", title: "Test product",
handle: "test-product", handle: "test-product",
images: expect.arrayContaining([
expect.objectContaining({
url: "test-image.png",
}),
expect.objectContaining({
url: "test-image-2.png",
}),
]),
thumbnail: "test-image.png",
tags: [ tags: [
expect.objectContaining({ expect.objectContaining({
value: "123", value: "123",
@@ -137,13 +148,15 @@ describe("/admin/products", () => {
); );
}); });
it("updates a product (update tags, delete collection, delete type)", async () => { it("updates a product (update tags, delete collection, delete type, replaces images)", async () => {
const api = useApi(); const api = useApi();
const payload = { const payload = {
collection_id: null, collection_id: null,
type: null, type: null,
tags: [{ value: "123" }], tags: [{ value: "123" }],
images: ["test-image-2.png"],
type: { value: "test-type-2" },
}; };
const response = await api const response = await api
@@ -160,6 +173,12 @@ describe("/admin/products", () => {
expect(response.data.product).toEqual( expect(response.data.product).toEqual(
expect.objectContaining({ expect.objectContaining({
images: expect.arrayContaining([
expect.objectContaining({
url: "test-image-2.png",
}),
]),
thumbnail: "test-image-2.png",
tags: [ tags: [
expect.objectContaining({ expect.objectContaining({
value: "123", value: "123",
@@ -167,6 +186,9 @@ describe("/admin/products", () => {
], ],
type: null, type: null,
collection: null, collection: null,
type: expect.objectContaining({
value: "test-type-2",
}),
}) })
); );
}); });
@@ -6,6 +6,7 @@ const {
Product, Product,
ShippingProfile, ShippingProfile,
ProductVariant, ProductVariant,
Image,
} = require("@medusajs/medusa"); } = require("@medusajs/medusa");
module.exports = async (connection, data = {}) => { module.exports = async (connection, data = {}) => {
@@ -36,6 +37,13 @@ module.exports = async (connection, data = {}) => {
await manager.save(type); await manager.save(type);
const image = manager.create(Image, {
id: "test-image",
url: "test-image.png",
});
await manager.save(image);
await manager.insert(Region, { await manager.insert(Region, {
id: "test-region", id: "test-region",
name: "Test Region", name: "Test Region",
@@ -43,7 +51,7 @@ module.exports = async (connection, data = {}) => {
tax_rate: 0, tax_rate: 0,
}); });
await manager.insert(Product, { const p = manager.create(Product, {
id: "test-product", id: "test-product",
title: "Test product", title: "Test product",
profile_id: defaultProfile.id, profile_id: defaultProfile.id,
@@ -57,6 +65,10 @@ module.exports = async (connection, data = {}) => {
options: [{ id: "test-option", title: "Default value" }], options: [{ id: "test-option", title: "Default value" }],
}); });
p.images = [image];
await manager.save(p);
await manager.insert(ProductVariant, { await manager.insert(ProductVariant, {
id: "test-variant", id: "test-variant",
inventory_quantity: 10, inventory_quantity: 10,
+1 -1
View File
@@ -46,7 +46,7 @@ export class Product {
@Column({ default: false }) @Column({ default: false })
is_giftcard: boolean is_giftcard: boolean
@ManyToMany(() => Image) @ManyToMany(() => Image, { cascade: ["insert"] })
@JoinTable({ @JoinTable({
name: "product_images", name: "product_images",
joinColumn: { joinColumn: {
@@ -0,0 +1,5 @@
import { EntityRepository, Repository } from "typeorm"
import { Image } from "../models/image"
@EntityRepository(Image)
export class ImageRepository extends Repository<Image> {}
+42 -3
View File
@@ -23,6 +23,7 @@ class ProductService extends BaseService {
productCollectionService, productCollectionService,
productTypeRepository, productTypeRepository,
productTagRepository, productTagRepository,
imageRepository,
}) { }) {
super() super()
@@ -52,6 +53,9 @@ class ProductService extends BaseService {
/** @private @const {ProductCollectionService} */ /** @private @const {ProductCollectionService} */
this.productTagRepository_ = productTagRepository this.productTagRepository_ = productTagRepository
/** @private @const {ImageRepository} */
this.imageRepository_ = imageRepository
} }
withTransaction(transactionManager) { withTransaction(transactionManager) {
@@ -69,6 +73,7 @@ class ProductService extends BaseService {
productCollectionService: this.productCollectionService_, productCollectionService: this.productCollectionService_,
productTagRepository: this.productTagRepository_, productTagRepository: this.productTagRepository_,
productTypeRepository: this.productTypeRepository_, productTypeRepository: this.productTypeRepository_,
imageRepository: this.imageRepository_,
}) })
cloned.transactionManager_ = transactionManager cloned.transactionManager_ = transactionManager
@@ -233,7 +238,7 @@ class ProductService extends BaseService {
}) })
if (existing) { if (existing) {
return existing return existing.id
} }
const created = productTypeRepository.create(type) const created = productTypeRepository.create(type)
@@ -277,10 +282,18 @@ class ProductService extends BaseService {
this.productOptionRepository_ this.productOptionRepository_
) )
const { options, tags, type, ...rest } = productObject const { options, tags, type, images, ...rest } = productObject
if (!rest.thumbnail && images && images.length) {
rest.thumbnail = images[0]
}
let product = productRepo.create(rest) let product = productRepo.create(rest)
if (images && images.length) {
product.images = await this.upsertImages_(images)
}
if (tags) { if (tags) {
product.tags = await this.upsertProductTags_(tags) product.tags = await this.upsertProductTags_(tags)
} }
@@ -310,6 +323,28 @@ class ProductService extends BaseService {
}) })
} }
async upsertImages_(images) {
const imageRepository = this.manager_.getCustomRepository(
this.imageRepository_
)
let productImages = []
for (const img of images) {
const existing = await imageRepository.findOne({
where: { url: img },
})
if (existing) {
productImages.push(existing)
} else {
const created = imageRepository.create({ url: img })
productImages.push(created)
}
}
return productImages
}
/** /**
* Updates a product. Product variant updates should use dedicated methods, * Updates a product. Product variant updates should use dedicated methods,
* e.g. `addVariant`, etc. The function will throw errors if metadata or * e.g. `addVariant`, etc. The function will throw errors if metadata or
@@ -327,7 +362,7 @@ class ProductService extends BaseService {
) )
const product = await this.retrieve(productId, { const product = await this.retrieve(productId, {
relations: ["variants", "tags"], relations: ["variants", "tags", "images"],
}) })
const { const {
@@ -344,6 +379,10 @@ class ProductService extends BaseService {
product.thumbnail = images[0] product.thumbnail = images[0]
} }
if (images && images.length) {
product.images = await this.upsertImages_(images)
}
if (metadata) { if (metadata) {
product.metadata = this.setMetadata_(product, metadata) product.metadata = this.setMetadata_(product, metadata)
} }