From 64afe158bb2ba002b286c02eb35a2d1508987eda Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Wed, 5 Feb 2020 16:38:52 +0100 Subject: [PATCH] Get region specific prices from the product variant service --- .../medusa/src/services/__mocks__/region.js | 18 +++++++ .../src/services/__tests__/product-variant.js | 42 +++++++++++++++ .../medusa/src/services/product-variant.js | 54 ++++++++++++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/packages/medusa/src/services/__mocks__/region.js b/packages/medusa/src/services/__mocks__/region.js index 1d356e346e..3f7d71bbcb 100644 --- a/packages/medusa/src/services/__mocks__/region.js +++ b/packages/medusa/src/services/__mocks__/region.js @@ -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 => { diff --git a/packages/medusa/src/services/__tests__/product-variant.js b/packages/medusa/src/services/__tests__/product-variant.js index 2f1bef9f00..772663a4a7 100644 --- a/packages/medusa/src/services/__tests__/product-variant.js +++ b/packages/medusa/src/services/__tests__/product-variant.js @@ -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" + ) + } + }) + }) }) diff --git a/packages/medusa/src/services/product-variant.js b/packages/medusa/src/services/product-variant.js index 767a9989b9..c9624eca17 100644 --- a/packages/medusa/src/services/product-variant.js +++ b/packages/medusa/src/services/product-variant.js @@ -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` ) }