Creates setRegion
This commit is contained in:
@@ -4,7 +4,7 @@ export const carts = {
|
||||
emptyCart: {
|
||||
_id: IdMap.getId("emptyCart"),
|
||||
title: "test",
|
||||
region: IdMap.getId("testRegion"),
|
||||
region_id: IdMap.getId("testRegion"),
|
||||
items: [],
|
||||
shippingAddress: {},
|
||||
billingAddress: {},
|
||||
@@ -12,9 +12,9 @@ export const carts = {
|
||||
customer_id: "",
|
||||
},
|
||||
cartWithLine: {
|
||||
_id: IdMap.getId("emptyCart"),
|
||||
_id: IdMap.getId("cartWithLine"),
|
||||
title: "test",
|
||||
region: IdMap.getId("testRegion"),
|
||||
region_id: IdMap.getId("testRegion"),
|
||||
items: [
|
||||
{
|
||||
_id: IdMap.getId("existingLine"),
|
||||
@@ -39,6 +39,99 @@ export const carts = {
|
||||
discounts: [],
|
||||
customer_id: "",
|
||||
},
|
||||
completeCart: {
|
||||
_id: IdMap.getId("complete-cart"),
|
||||
title: "test",
|
||||
region_id: IdMap.getId("region-france"),
|
||||
items: [],
|
||||
payment_method: {
|
||||
provider_id: "stripe",
|
||||
data: {
|
||||
yes: "sir",
|
||||
},
|
||||
},
|
||||
shipping_method: {
|
||||
provider_id: "gls",
|
||||
data: {
|
||||
yes: "sir",
|
||||
},
|
||||
},
|
||||
shipping_address: {
|
||||
first_name: "hi",
|
||||
last_name: "you",
|
||||
country_code: "DK",
|
||||
city: "of lights",
|
||||
address_1: "You bet street",
|
||||
postal_code: "4242",
|
||||
},
|
||||
billing_address: {
|
||||
first_name: "hi",
|
||||
last_name: "you",
|
||||
country_code: "DK",
|
||||
city: "of lights",
|
||||
address_1: "You bet street",
|
||||
postal_code: "4242",
|
||||
},
|
||||
discounts: [],
|
||||
customer_id: "",
|
||||
},
|
||||
frCart: {
|
||||
_id: IdMap.getId("fr-cart"),
|
||||
title: "test",
|
||||
region_id: IdMap.getId("region-france"),
|
||||
items: [
|
||||
{
|
||||
_id: IdMap.getId("line"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: [
|
||||
{
|
||||
unit_price: 8,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-8-us-10"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
{
|
||||
unit_price: 10,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
quantity: 10,
|
||||
},
|
||||
{
|
||||
_id: IdMap.getId("existingLine"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: {
|
||||
unit_price: 10,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
shippingAddress: {},
|
||||
billingAddress: {},
|
||||
discounts: [],
|
||||
customer_id: "",
|
||||
},
|
||||
}
|
||||
|
||||
export const CartModelMock = {
|
||||
@@ -54,6 +147,12 @@ export const CartModelMock = {
|
||||
if (query._id === IdMap.getId("cartWithLine")) {
|
||||
return Promise.resolve(carts.cartWithLine)
|
||||
}
|
||||
if (query._id === IdMap.getId("fr-cart")) {
|
||||
return Promise.resolve(carts.frCart)
|
||||
}
|
||||
if (query._id === IdMap.getId("complete-cart")) {
|
||||
return Promise.resolve(carts.completeCart)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class CartModel extends BaseModel {
|
||||
billing_address: { type: AddressSchema },
|
||||
shipping_address: { type: AddressSchema },
|
||||
items: { type: [LineItemSchema], default: [] },
|
||||
region: { type: String, required: true },
|
||||
region_id: { type: String },
|
||||
discounts: { type: [String], default: [] },
|
||||
customer_id: { type: String },
|
||||
payment_method: { type: PaymentMethodSchema },
|
||||
|
||||
@@ -141,6 +141,25 @@ export const ProductVariantServiceMock = {
|
||||
|
||||
return Promise.reject(new Error("Not found"))
|
||||
}),
|
||||
getRegionPrice: jest.fn().mockImplementation((variantId, regionId) => {
|
||||
if (variantId === IdMap.getId("eur-10-us-12")) {
|
||||
if (regionId === IdMap.getId("region-france")) {
|
||||
return Promise.resolve(10)
|
||||
} else {
|
||||
return Promise.resolve(12)
|
||||
}
|
||||
}
|
||||
|
||||
if (variantId === IdMap.getId("eur-8-us-10")) {
|
||||
if (regionId === IdMap.getId("region-france")) {
|
||||
return Promise.resolve(8)
|
||||
} else {
|
||||
return Promise.resolve(10)
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(new Error("Not found"))
|
||||
}),
|
||||
delete: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
addOptionValue: jest.fn().mockImplementation((variantId, optionId, value) => {
|
||||
return Promise.resolve({})
|
||||
|
||||
@@ -452,4 +452,120 @@ describe("CartService", () => {
|
||||
expect(CartModelMock.updateOne).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("setRegion", () => {
|
||||
const cartService = new CartService({
|
||||
cartModel: CartModelMock,
|
||||
regionService: RegionServiceMock,
|
||||
productVariantService: ProductVariantServiceMock,
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("successfully set new region", async () => {
|
||||
await cartService.setRegion(
|
||||
IdMap.getId("fr-cart"),
|
||||
IdMap.getId("region-us")
|
||||
)
|
||||
|
||||
expect(CartModelMock.updateOne).toHaveBeenCalledTimes(1)
|
||||
expect(CartModelMock.updateOne).toHaveBeenCalledWith(
|
||||
{
|
||||
_id: IdMap.getId("fr-cart"),
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
region_id: IdMap.getId("region-us"),
|
||||
items: [
|
||||
{
|
||||
_id: IdMap.getId("line"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: [
|
||||
{
|
||||
unit_price: 10,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-8-us-10"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
{
|
||||
unit_price: 12,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
quantity: 10,
|
||||
},
|
||||
{
|
||||
_id: IdMap.getId("existingLine"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: {
|
||||
unit_price: 12,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("successfully set new region", async () => {
|
||||
await cartService.setRegion(
|
||||
IdMap.getId("complete-cart"),
|
||||
IdMap.getId("region-us")
|
||||
)
|
||||
|
||||
expect(CartModelMock.updateOne).toHaveBeenCalledTimes(1)
|
||||
expect(CartModelMock.updateOne).toHaveBeenCalledWith(
|
||||
{
|
||||
_id: IdMap.getId("complete-cart"),
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
region_id: IdMap.getId("region-us"),
|
||||
shipping_method: undefined,
|
||||
payment_method: undefined,
|
||||
shipping_address: {
|
||||
first_name: "hi",
|
||||
last_name: "you",
|
||||
country_code: "",
|
||||
city: "of lights",
|
||||
address_1: "You bet street",
|
||||
postal_code: "4242",
|
||||
},
|
||||
billing_address: {
|
||||
first_name: "hi",
|
||||
last_name: "you",
|
||||
country_code: "",
|
||||
city: "of lights",
|
||||
address_1: "You bet street",
|
||||
postal_code: "4242",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -138,6 +138,38 @@ class CartService extends BaseService {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms some line item content to have unit_prices corresponding to a
|
||||
* given region's pricing scheme.
|
||||
* @param {(LineItemContent | LineItemContentArray)} - the content of the line
|
||||
* item
|
||||
* @param {string} regionId - the id of the region whose price we should
|
||||
* update to
|
||||
* @return {(LineItemContent | LineItemContentArray)} true if the inventory
|
||||
* covers the line item.
|
||||
*/
|
||||
async updateContentPrice_(content, regionId) {
|
||||
if (Array.isArray(content)) {
|
||||
return await Promise.all(
|
||||
content.map(async c => {
|
||||
const unitPrice = await this.productVariantService_.getRegionPrice(
|
||||
c.variant._id,
|
||||
regionId
|
||||
)
|
||||
c.unit_price = unitPrice
|
||||
return c
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const unitPrice = await this.productVariantService_.getRegionPrice(
|
||||
content.variant._id,
|
||||
regionId
|
||||
)
|
||||
content.unit_price = unitPrice
|
||||
return content
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @return {Promise} the result of the find operation
|
||||
@@ -348,18 +380,70 @@ class CartService extends BaseService {
|
||||
* @param {string} regionId - the id of the region to set the cart to
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
setRegion(cartId, regionId) {
|
||||
// Check if cart exists
|
||||
// Check if region exists
|
||||
//
|
||||
// If the cart already has items, go through the items and update the prices
|
||||
// based on new tax rate, new currency, region specific pricing.
|
||||
//
|
||||
// If addresses are set, clear the country code.
|
||||
//
|
||||
// If the cart has a shipping method, clear this.
|
||||
//
|
||||
// Update the region
|
||||
async setRegion(cartId, regionId) {
|
||||
const cart = await this.retrieve(cartId)
|
||||
if (!cart) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
"The cart was not found"
|
||||
)
|
||||
}
|
||||
|
||||
const region = await this.regionService_.retrieve(regionId)
|
||||
if (!region) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`The region: ${regionId} was not found`
|
||||
)
|
||||
}
|
||||
|
||||
let update = {
|
||||
region_id: region._id,
|
||||
}
|
||||
|
||||
// If the cart contains items we want to change the unit_price field of each
|
||||
// item to correspond to the price given in the region
|
||||
if (cart.items.length) {
|
||||
const newItems = await Promise.all(
|
||||
cart.items.map(async lineItem => {
|
||||
lineItem.content = await this.updateContentPrice_(
|
||||
lineItem.content,
|
||||
region._id
|
||||
)
|
||||
return lineItem
|
||||
})
|
||||
)
|
||||
|
||||
update.items = newItems
|
||||
}
|
||||
|
||||
// If the country code of a shipping address is set we need to clear it
|
||||
let shippingAddress = cart.shipping_address
|
||||
if (!_.isEmpty(shippingAddress) && shippingAddress.country_code) {
|
||||
shippingAddress.country_code = ""
|
||||
update.shipping_address = shippingAddress
|
||||
}
|
||||
|
||||
// If the country code of a billing address is set we need to clear it
|
||||
let billingAddress = cart.billing_address
|
||||
if (!_.isEmpty(billingAddress) && billingAddress.country_code) {
|
||||
billingAddress.country_code = ""
|
||||
update.billing_address = billingAddress
|
||||
}
|
||||
|
||||
// Shipping methods are determined by region so the user needs to find a
|
||||
// new shipping method
|
||||
if (!_.isEmpty(cart.shipping_method)) {
|
||||
update.shipping_method = undefined
|
||||
}
|
||||
|
||||
// Payment methods are region specific so the user needs to find a
|
||||
// new payment method
|
||||
if (!_.isEmpty(cart.payment_method)) {
|
||||
update.payment_method = undefined
|
||||
}
|
||||
|
||||
return this.cartModel_.updateOne({ _id: cart._id }, { $set: update })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user