fix: merge api
This commit is contained in:
commit
6ad2b0e6e9
35 files changed
+5117
-2358
No files matched your search
@@ -11,6 +11,9 @@ describe("POST /store/carts", () => {
|
||||
subject = await request("POST", `/store/carts`, {
|
||||
payload: {
|
||||
region_id: IdMap.getId("testRegion"),
|
||||
context: {
|
||||
clientId: "test",
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -23,6 +26,11 @@ describe("POST /store/carts", () => {
|
||||
expect(CartServiceMock.create).toHaveBeenCalledTimes(1)
|
||||
expect(CartServiceMock.create).toHaveBeenCalledWith({
|
||||
region_id: IdMap.getId("testRegion"),
|
||||
context: {
|
||||
ip: "::ffff:127.0.0.1",
|
||||
user_agent: "node-superagent/3.8.3",
|
||||
clientId: "test",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import reqIp from "request-ip"
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { defaultFields, defaultRelations } from "./"
|
||||
|
||||
@@ -31,6 +32,9 @@ import { defaultFields, defaultRelations } from "./"
|
||||
* quantity:
|
||||
* description: The quantity of the Product Variant to add
|
||||
* type: integer
|
||||
* context:
|
||||
* description: "An optional object to provide context to the Cart. The `context` field is automatically populated with `ip` and `user_agent`"
|
||||
* type: object
|
||||
* tags:
|
||||
* - Cart
|
||||
* responses:
|
||||
@@ -53,6 +57,7 @@ export default async (req, res) => {
|
||||
quantity: Validator.number().required(),
|
||||
})
|
||||
.optional(),
|
||||
context: Validator.object().optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
@@ -60,6 +65,11 @@ export default async (req, res) => {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
const reqContext = {
|
||||
ip: reqIp.getClientIp(req),
|
||||
user_agent: req.get("user-agent"),
|
||||
}
|
||||
|
||||
try {
|
||||
const lineItemService = req.scope.resolve("lineItemService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
@@ -77,6 +87,10 @@ export default async (req, res) => {
|
||||
|
||||
const toCreate = {
|
||||
region_id: regionId,
|
||||
context: {
|
||||
...reqContext,
|
||||
...value.context,
|
||||
},
|
||||
}
|
||||
|
||||
if (req.user && req.user.customer_id) {
|
||||
|
||||
@@ -51,6 +51,9 @@ import { defaultFields, defaultRelations } from "./"
|
||||
* customer_id:
|
||||
* description: "The id of the Customer to associate the Cart with."
|
||||
* type: string
|
||||
* context:
|
||||
* description: "An optional object to provide context to the Cart."
|
||||
* type: object
|
||||
* tags:
|
||||
* - Cart
|
||||
* responses:
|
||||
@@ -85,6 +88,7 @@ export default async (req, res) => {
|
||||
})
|
||||
.optional(),
|
||||
customer_id: Validator.string().optional(),
|
||||
context: Validator.object().optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* summary: Retrieve Shipping Options
|
||||
* description: "Retrieves a list of Shipping Options."
|
||||
* parameters:
|
||||
* - (query) is_return {boolean} Whether return Shipping Options should be included. By default all Shipping Options are returned.
|
||||
* - (query) product_ids {string} A comma separated list of Product ids to filter Shipping Options by.
|
||||
* - (query) region_id {string} the Region to retrieve Shipping Options from.
|
||||
* tags:
|
||||
@@ -31,6 +32,10 @@ export default async (req, res) => {
|
||||
|
||||
const query = {}
|
||||
|
||||
if ("is_return" in req.query) {
|
||||
query.is_return = req.query.is_return === "true"
|
||||
}
|
||||
|
||||
if (regionId) {
|
||||
query.region_id = regionId
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class cartContext1614684597235 implements MigrationInterface {
|
||||
name = "cartContext1614684597235"
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "cart" ADD "context" jsonb`)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "cart" DROP COLUMN "context"`)
|
||||
}
|
||||
}
|
||||
@@ -243,6 +243,9 @@ export class Cart {
|
||||
@Column({ nullable: true })
|
||||
idempotency_key: string
|
||||
|
||||
@Column({ type: "jsonb", nullable: true })
|
||||
context: any
|
||||
|
||||
// Total fields
|
||||
shipping_total: number
|
||||
discount_total: number
|
||||
|
||||
@@ -46,7 +46,7 @@ export class Product {
|
||||
@Column({ default: false })
|
||||
is_giftcard: boolean
|
||||
|
||||
@ManyToMany(() => Image)
|
||||
@ManyToMany(() => Image, { cascade: ["insert"] })
|
||||
@JoinTable({
|
||||
name: "product_images",
|
||||
joinColumn: {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { EntityRepository, Repository } from "typeorm"
|
||||
import { Image } from "../models/image"
|
||||
|
||||
@EntityRepository(Image)
|
||||
export class ImageRepository extends Repository<Image> {}
|
||||
@@ -641,6 +641,14 @@ class CartService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
if ("context" in update) {
|
||||
const prevContext = cart.context || {}
|
||||
cart.context = {
|
||||
...prevContext,
|
||||
...update.context,
|
||||
}
|
||||
}
|
||||
|
||||
const result = await cartRepo.save(cart)
|
||||
|
||||
if ("email" in update || "customer_id" in update) {
|
||||
|
||||
@@ -23,6 +23,7 @@ class ProductService extends BaseService {
|
||||
productCollectionService,
|
||||
productTypeRepository,
|
||||
productTagRepository,
|
||||
imageRepository,
|
||||
}) {
|
||||
super()
|
||||
|
||||
@@ -52,6 +53,9 @@ class ProductService extends BaseService {
|
||||
|
||||
/** @private @const {ProductCollectionService} */
|
||||
this.productTagRepository_ = productTagRepository
|
||||
|
||||
/** @private @const {ImageRepository} */
|
||||
this.imageRepository_ = imageRepository
|
||||
}
|
||||
|
||||
withTransaction(transactionManager) {
|
||||
@@ -69,6 +73,7 @@ class ProductService extends BaseService {
|
||||
productCollectionService: this.productCollectionService_,
|
||||
productTagRepository: this.productTagRepository_,
|
||||
productTypeRepository: this.productTypeRepository_,
|
||||
imageRepository: this.imageRepository_,
|
||||
})
|
||||
|
||||
cloned.transactionManager_ = transactionManager
|
||||
@@ -233,7 +238,7 @@ class ProductService extends BaseService {
|
||||
})
|
||||
|
||||
if (existing) {
|
||||
return existing
|
||||
return existing.id
|
||||
}
|
||||
|
||||
const created = productTypeRepository.create(type)
|
||||
@@ -277,10 +282,18 @@ class ProductService extends BaseService {
|
||||
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)
|
||||
|
||||
if (images && images.length) {
|
||||
product.images = await this.upsertImages_(images)
|
||||
}
|
||||
|
||||
if (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,
|
||||
* 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, {
|
||||
relations: ["variants", "tags"],
|
||||
relations: ["variants", "tags", "images"],
|
||||
})
|
||||
|
||||
const {
|
||||
@@ -344,6 +379,10 @@ class ProductService extends BaseService {
|
||||
product.thumbnail = images[0]
|
||||
}
|
||||
|
||||
if (images && images.length) {
|
||||
product.images = await this.upsertImages_(images)
|
||||
}
|
||||
|
||||
if (metadata) {
|
||||
product.metadata = this.setMetadata_(product, metadata)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user