Get region specific prices from the product variant service

This commit is contained in:
Sebastian Rindom
2020-02-05 16:38:52 +01:00
parent 8fb5845874
commit 64afe158bb
3 changed files with 113 additions and 1 deletions

View File

@@ -22,6 +22,18 @@ export const regions = {
countries: ["US"],
currency_code: "usd",
},
regionGermany: {
_id: IdMap.getId("region-de"),
name: "Germany",
countries: ["DE"],
currency_code: "eur",
},
regionSweden: {
_id: IdMap.getId("region-se"),
name: "Sweden",
countries: ["SE"],
currency_code: "sek",
},
}
export const RegionServiceMock = {
@@ -35,6 +47,12 @@ export const RegionServiceMock = {
if (regionId === IdMap.getId("region-us")) {
return Promise.resolve(regions.regionUs)
}
if (regionId === IdMap.getId("region-de")) {
return Promise.resolve(regions.regionGermany)
}
if (regionId === IdMap.getId("region-se")) {
return Promise.resolve(regions.regionSweden)
}
return Promise.resolve(undefined)
}),
list: jest.fn().mockImplementation(data => {

View File

@@ -659,4 +659,46 @@ describe("ProductVariantService", () => {
)
})
})
describe("getRegionPrice", () => {
const productVariantService = new ProductVariantService({
productVariantModel: ProductVariantModelMock,
regionService: RegionServiceMock,
})
beforeEach(() => {
jest.clearAllMocks()
})
it("gets region specific price", async () => {
const res = await productVariantService.getRegionPrice(
IdMap.getId("eur-prices"),
IdMap.getId("region-france")
)
expect(res).toEqual(950)
})
it("gets currency default price", async () => {
const res = await productVariantService.getRegionPrice(
IdMap.getId("eur-prices"),
IdMap.getId("region-de")
)
expect(res).toEqual(1000)
})
it("throws if no region or currency", async () => {
try {
const res = await productVariantService.getRegionPrice(
IdMap.getId("eur-prices"),
IdMap.getId("region-se")
)
} catch (err) {
expect(err.message).toEqual(
"A price for region: Sweden could not be found"
)
}
})
})
})

View File

@@ -196,6 +196,58 @@ class ProductVariantService extends BaseService {
)
}
/**
* Gets the price specific to a region. If no region specific money amount
* exists the function will try to use a currency price. If no default
* currency price exists the function will throw an error.
* @param {string} variantId - the id of the variant to get price from
* @param {string} regionId - the id of the region to get price for
* @return {number} the price specific to the region
*/
async getRegionPrice(variantId, regionId) {
const variant = await this.retrieve(variantId)
if (!variant) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Variant: ${variantId} was not found`
)
}
const region = await this.regionService_.retrieve(regionId)
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${regionId} was not found`
)
}
let price
variant.prices.forEach(({ region_id, amount, currency_code }) => {
if (!price && !region_id && currency_code === region.currency_code) {
// If we haven't yet found a price and the current money amount is
// the default money amount for the currency of the region we have found
// a possible price match
price = amount
} else if (region_id === region._id) {
// If the region matches directly with the money amount this is the best
// price
price = amount
}
})
// Return the price if we found a suitable match
if (price) {
return price
}
// If we got this far no price could be found for the region
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`A price for region: ${region.name} could not be found`
)
}
/**
* Sets the price of a specific region
* @param {string} variantId - the id of the variant to update
@@ -216,7 +268,7 @@ class ProductVariantService extends BaseService {
if (!region) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Region: ${region} was not found`
`Region: ${regionId} was not found`
)
}