Merge branch 'master' of github.com:medusajs/medusa
This commit is contained in:
commit
81fc7d9f2e
13 files changed
+129
-42
No files matched your search
@@ -0,0 +1,17 @@
|
|||||||
|
import _ from "lodash"
|
||||||
|
|
||||||
|
function compareObjectsByProp(object1, object2, prop) {
|
||||||
|
if (Array.isArray(object1[prop])) {
|
||||||
|
object2[prop] = object2[prop].map(({ _id, ...rest }) => rest)
|
||||||
|
return (
|
||||||
|
_.differenceWith(object1[prop], object2[prop], _.isEqual).length === 0
|
||||||
|
)
|
||||||
|
} else if (typeof object1[prop] === "object") {
|
||||||
|
delete object2[prop]._id
|
||||||
|
return _.isEqual(object1[prop], object2[prop])
|
||||||
|
} else {
|
||||||
|
return object1[prop] === object2[prop]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compareObjectsByProp
|
||||||
@@ -2,3 +2,4 @@ export { default as Validator } from "./validator"
|
|||||||
export { default as MedusaError } from "./errors"
|
export { default as MedusaError } from "./errors"
|
||||||
export { default as getConfigFile } from "./get-config-file"
|
export { default as getConfigFile } from "./get-config-file"
|
||||||
export { default as createRequireFromPath } from "./create-require-from-path"
|
export { default as createRequireFromPath } from "./create-require-from-path"
|
||||||
|
export { default as compareObjectsByProp } from "./compare-objects"
|
||||||
@@ -67,8 +67,16 @@ class BaseModel {
|
|||||||
* @return {Array<mongoose.Document>} the retreived mongoose documents or
|
* @return {Array<mongoose.Document>} the retreived mongoose documents or
|
||||||
* an empty array
|
* an empty array
|
||||||
*/
|
*/
|
||||||
find(query, options) {
|
find(query, options, offset, limit) {
|
||||||
return this.mongooseModel_.find(query, options).lean()
|
return this.mongooseModel_
|
||||||
|
.find(query, options)
|
||||||
|
.skip(offset)
|
||||||
|
.limit(limit)
|
||||||
|
.lean()
|
||||||
|
}
|
||||||
|
|
||||||
|
count() {
|
||||||
|
return this.mongooseModel_.count({})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ const route = Router()
|
|||||||
export default (app) => {
|
export default (app) => {
|
||||||
app.use("/hooks", route)
|
app.use("/hooks", route)
|
||||||
|
|
||||||
route.post("/contentful", middlewares.wrap(require("./contentful").default))
|
route.post(
|
||||||
|
"/contentful",
|
||||||
|
bodyParser.json(),
|
||||||
|
middlewares.wrap(require("./contentful").default)
|
||||||
|
)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,9 @@ class ContentfulService extends BaseService {
|
|||||||
|
|
||||||
const variantEntries = await this.getVariantEntries_(product._id)
|
const variantEntries = await this.getVariantEntries_(product._id)
|
||||||
const variantLinks = this.getVariantLinks_(variantEntries)
|
const variantLinks = this.getVariantLinks_(variantEntries)
|
||||||
productEntry.fields = _.assignIn(productEntry.fields, {
|
|
||||||
|
const productEntryFields = {
|
||||||
|
...productEntry.fields,
|
||||||
title: {
|
title: {
|
||||||
"en-US": product.title,
|
"en-US": product.title,
|
||||||
},
|
},
|
||||||
@@ -181,7 +183,9 @@ class ContentfulService extends BaseService {
|
|||||||
objectId: {
|
objectId: {
|
||||||
"en-US": product._id,
|
"en-US": product._id,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
|
productEntry.fields = productEntryFields
|
||||||
|
|
||||||
const updatedEntry = await productEntry.update()
|
const updatedEntry = await productEntry.update()
|
||||||
const publishedEntry = await updatedEntry.publish()
|
const publishedEntry = await updatedEntry.publish()
|
||||||
@@ -218,7 +222,8 @@ class ContentfulService extends BaseService {
|
|||||||
return this.createProductVariantInContentful(variant)
|
return this.createProductVariantInContentful(variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
variantEntry.fields = _.assignIn(variantEntry.fields, {
|
const variantEntryFields = {
|
||||||
|
...variantEntry.fields,
|
||||||
title: {
|
title: {
|
||||||
"en-US": variant.title,
|
"en-US": variant.title,
|
||||||
},
|
},
|
||||||
@@ -234,7 +239,9 @@ class ContentfulService extends BaseService {
|
|||||||
objectId: {
|
objectId: {
|
||||||
"en-US": variant._id,
|
"en-US": variant._id,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
|
variantEntry.fields = variantEntryFields
|
||||||
|
|
||||||
const updatedEntry = await variantEntry.update()
|
const updatedEntry = await variantEntry.update()
|
||||||
const publishedEntry = await updatedEntry.publish()
|
const publishedEntry = await updatedEntry.publish()
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { MedusaError, Validator } from "medusa-core-utils"
|
|||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { discount_id } = req.params
|
const { discount_id } = req.params
|
||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
code: Validator.string().required(),
|
code: Validator.string().optional(),
|
||||||
is_dynamic: Validator.boolean().default(false),
|
is_dynamic: Validator.boolean().default(false),
|
||||||
|
is_giftcard: Validator.boolean().optional(),
|
||||||
discount_rule: Validator.object()
|
discount_rule: Validator.object()
|
||||||
.keys({
|
.keys({
|
||||||
description: Validator.string().optional(),
|
description: Validator.string().optional(),
|
||||||
@@ -14,7 +15,7 @@ export default async (req, res) => {
|
|||||||
valid_for: Validator.array().items(Validator.string()),
|
valid_for: Validator.array().items(Validator.string()),
|
||||||
usage_limit: Validator.number().optional(),
|
usage_limit: Validator.number().optional(),
|
||||||
})
|
})
|
||||||
.required(),
|
.optional(),
|
||||||
usage_count: Validator.number().optional(),
|
usage_count: Validator.number().optional(),
|
||||||
disabled: Validator.boolean().optional(),
|
disabled: Validator.boolean().optional(),
|
||||||
starts_at: Validator.date().optional(),
|
starts_at: Validator.date().optional(),
|
||||||
|
|||||||
@@ -6,19 +6,25 @@ export default async (req, res) => {
|
|||||||
const queryBuilderService = req.scope.resolve("queryBuilderService")
|
const queryBuilderService = req.scope.resolve("queryBuilderService")
|
||||||
|
|
||||||
const query = queryBuilderService.buildQuery(req.query, [
|
const query = queryBuilderService.buildQuery(req.query, [
|
||||||
|
"display_id",
|
||||||
"email",
|
"email",
|
||||||
"status",
|
"status",
|
||||||
"fulfillment_status",
|
"fulfillment_status",
|
||||||
"payment_status",
|
"payment_status",
|
||||||
])
|
])
|
||||||
|
|
||||||
let orders = await orderService.list(query)
|
const limit = parseInt(req.query.limit) || 0
|
||||||
|
const offset = parseInt(req.query.offset) || 0
|
||||||
|
|
||||||
|
let orders = await orderService.list(query, offset, limit)
|
||||||
|
|
||||||
orders = await Promise.all(
|
orders = await Promise.all(
|
||||||
orders.map(order => orderService.decorate(order))
|
orders.map(order => orderService.decorate(order))
|
||||||
)
|
)
|
||||||
|
|
||||||
res.json({ orders })
|
let numOrders = await orderService.count()
|
||||||
|
|
||||||
|
res.json({ orders, total_count: numOrders })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ export default async (req, res) => {
|
|||||||
"description",
|
"description",
|
||||||
])
|
])
|
||||||
|
|
||||||
let products = await productService.list(query)
|
const limit = parseInt(req.query.limit) || 0
|
||||||
|
const offset = parseInt(req.query.offset) || 0
|
||||||
|
|
||||||
|
let products = await productService.list(query, offset, limit)
|
||||||
|
|
||||||
products = await Promise.all(
|
products = await Promise.all(
|
||||||
products.map(
|
products.map(
|
||||||
@@ -32,7 +35,10 @@ export default async (req, res) => {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
res.json({ products })
|
|
||||||
|
const numProducts = await productService.count()
|
||||||
|
|
||||||
|
res.json({ products, total_count: numProducts })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
throw error
|
throw error
|
||||||
|
|||||||
@@ -10,14 +10,7 @@ describe("Get product by id", () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
subject = await request(
|
subject = await request(
|
||||||
"GET",
|
"GET",
|
||||||
`/admin/products/${IdMap.getId("product1")}`,
|
`/store/products/${IdMap.getId("product1")}`
|
||||||
{
|
|
||||||
adminSession: {
|
|
||||||
jwt: {
|
|
||||||
userId: IdMap.getId("admin_user"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export const MiddlewareServiceMock = {
|
export const MiddlewareServiceMock = {
|
||||||
usePostAuthentication: jest.fn(),
|
usePostAuthentication: jest.fn(),
|
||||||
usePreAuthentication: jest.fn(),
|
usePreAuthentication: jest.fn(),
|
||||||
|
usePreCartCreation: jest.fn().mockReturnValue([]),
|
||||||
getRouters: jest.fn().mockReturnValue([]),
|
getRouters: jest.fn().mockReturnValue([]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,8 +145,18 @@ class OrderService extends BaseService {
|
|||||||
* @param {Object} selector - the query object for find
|
* @param {Object} selector - the query object for find
|
||||||
* @return {Promise} the result of the find operation
|
* @return {Promise} the result of the find operation
|
||||||
*/
|
*/
|
||||||
list(selector) {
|
list(selector, offset, limit) {
|
||||||
return this.orderModel_.find(selector)
|
return this.orderModel_
|
||||||
|
.find(selector, {}, offset, limit)
|
||||||
|
.sort({ created: -1 })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the total number of documents in database
|
||||||
|
* @return {Promise} the result of the count operation
|
||||||
|
*/
|
||||||
|
count() {
|
||||||
|
return this.orderModel_.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,14 +242,6 @@ class OrderService extends BaseService {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Object} selector - the query object for find
|
|
||||||
* @return {Promise} the result of the find operation
|
|
||||||
*/
|
|
||||||
list(selector) {
|
|
||||||
return this.orderModel_.find(selector)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} orderId - id of the order to complete
|
* @param {string} orderId - id of the order to complete
|
||||||
* @return {Promise} the result of the find operation
|
* @return {Promise} the result of the find operation
|
||||||
@@ -247,9 +249,6 @@ class OrderService extends BaseService {
|
|||||||
async completeOrder(orderId) {
|
async completeOrder(orderId) {
|
||||||
const order = await this.retrieve(orderId)
|
const order = await this.retrieve(orderId)
|
||||||
|
|
||||||
// Capture the payment
|
|
||||||
await this.capturePayment(orderId)
|
|
||||||
|
|
||||||
// Run all other registered events
|
// Run all other registered events
|
||||||
const completeOrderJob = await this.eventBus_.emit(
|
const completeOrderJob = await this.eventBus_.emit(
|
||||||
OrderService.Events.COMPLETED,
|
OrderService.Events.COMPLETED,
|
||||||
@@ -593,12 +592,7 @@ class OrderService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare update object
|
|
||||||
const updateFields = { payment_status: "captured" }
|
const updateFields = { payment_status: "captured" }
|
||||||
const completed = order.fulfillment_status !== "not_fulfilled"
|
|
||||||
if (completed) {
|
|
||||||
updateFields.status = "completed"
|
|
||||||
}
|
|
||||||
|
|
||||||
const { provider_id, data } = order.payment_method
|
const { provider_id, data } = order.payment_method
|
||||||
const paymentProvider = await this.paymentProviderService_.retrieveProvider(
|
const paymentProvider = await this.paymentProviderService_.retrieveProvider(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import mongoose from "mongoose"
|
import mongoose from "mongoose"
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
import { Validator, MedusaError } from "medusa-core-utils"
|
import { Validator, MedusaError, compareObjectsByProp } from "medusa-core-utils"
|
||||||
import { BaseService } from "medusa-interfaces"
|
import { BaseService } from "medusa-interfaces"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,8 +49,16 @@ class ProductService extends BaseService {
|
|||||||
* @param {Object} selector - the query object for find
|
* @param {Object} selector - the query object for find
|
||||||
* @return {Promise} the result of the find operation
|
* @return {Promise} the result of the find operation
|
||||||
*/
|
*/
|
||||||
list(selector) {
|
list(selector, offset, limit) {
|
||||||
return this.productModel_.find(selector)
|
return this.productModel_.find(selector, {}, offset, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the total number of documents in database
|
||||||
|
* @return {Promise} the result of the count operation
|
||||||
|
*/
|
||||||
|
count() {
|
||||||
|
return this.productModel_.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,7 +161,18 @@ class ProductService extends BaseService {
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
update.variants.map(async variant => {
|
update.variants.map(async variant => {
|
||||||
if (variant._id) {
|
if (variant._id) {
|
||||||
|
const variantFromDb = existingVariants.find(v =>
|
||||||
|
v._id.equals(variant._id)
|
||||||
|
)
|
||||||
if (variant.prices && variant.prices.length) {
|
if (variant.prices && variant.prices.length) {
|
||||||
|
// if equal we dont want to update
|
||||||
|
const isPricesEqual = compareObjectsByProp(
|
||||||
|
variant,
|
||||||
|
variantFromDb,
|
||||||
|
"prices"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isPricesEqual) {
|
||||||
for (const price of variant.prices) {
|
for (const price of variant.prices) {
|
||||||
if (price.region_id) {
|
if (price.region_id) {
|
||||||
await this.productVariantService_.setRegionPrice(
|
await this.productVariantService_.setRegionPrice(
|
||||||
@@ -170,8 +189,17 @@ class ProductService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (variant.options && variant.options.length) {
|
if (variant.options && variant.options.length) {
|
||||||
|
// if equal we dont want to update
|
||||||
|
const isOptionsEqual = compareObjectsByProp(
|
||||||
|
variant,
|
||||||
|
variantFromDb,
|
||||||
|
"options"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isOptionsEqual) {
|
||||||
for (const option of variant.options) {
|
for (const option of variant.options) {
|
||||||
await this.updateOptionValue(
|
await this.updateOptionValue(
|
||||||
productId,
|
productId,
|
||||||
@@ -181,6 +209,7 @@ class ProductService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete variant.prices
|
delete variant.prices
|
||||||
delete variant.options
|
delete variant.options
|
||||||
|
|||||||
@@ -1965,6 +1965,13 @@ cli-width@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
||||||
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
|
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
|
||||||
|
|
||||||
|
client-sessions@^0.8.0:
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/client-sessions/-/client-sessions-0.8.0.tgz#a7d8c5558ad5d56f2a199f3533eb654b5df893fd"
|
||||||
|
integrity sha1-p9jFVYrV1W8qGZ81M+tlS134k/0=
|
||||||
|
dependencies:
|
||||||
|
cookies "^0.7.0"
|
||||||
|
|
||||||
cliui@^6.0.0:
|
cliui@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||||
@@ -2171,6 +2178,14 @@ cookiejar@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
|
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
|
||||||
integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==
|
integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==
|
||||||
|
|
||||||
|
cookies@^0.7.0:
|
||||||
|
version "0.7.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.3.tgz#7912ce21fbf2e8c2da70cf1c3f351aecf59dadfa"
|
||||||
|
integrity sha512-+gixgxYSgQLTaTIilDHAdlNPZDENDQernEMiIcZpYYP14zgHsCt4Ce1FEjFtcp6GefhozebB6orvhAAWx/IS0A==
|
||||||
|
dependencies:
|
||||||
|
depd "~1.1.2"
|
||||||
|
keygrip "~1.0.3"
|
||||||
|
|
||||||
copy-descriptor@^0.1.0:
|
copy-descriptor@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||||
@@ -4348,6 +4363,11 @@ kareem@2.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.1.tgz#def12d9c941017fabfb00f873af95e9c99e1be87"
|
resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.1.tgz#def12d9c941017fabfb00f873af95e9c99e1be87"
|
||||||
integrity sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==
|
integrity sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==
|
||||||
|
|
||||||
|
keygrip@~1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc"
|
||||||
|
integrity sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==
|
||||||
|
|
||||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||||
|
|||||||
Reference in new issue
Block a user