diff --git a/lerna.json b/lerna.json index 2699b7d05e..d84be0597c 100644 --- a/lerna.json +++ b/lerna.json @@ -4,5 +4,5 @@ "packages/*" ], "registry": "https://registry.npmjs.org/", - "version": "1.0.0-y.18" + "version": "1.0.0-y.24" } diff --git a/packages/medusa-plugin-brightpearl/package.json b/packages/medusa-plugin-brightpearl/package.json index 3604e83a3d..bcb9b2d7da 100644 --- a/packages/medusa-plugin-brightpearl/package.json +++ b/packages/medusa-plugin-brightpearl/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-brightpearl", - "version": "1.0.0-alpha.33", + "version": "1.0.0-y.23", "description": "Brightpearl plugin for Medusa Commerce", "main": "index.js", "repository": { diff --git a/packages/medusa-plugin-brightpearl/src/api/index.js b/packages/medusa-plugin-brightpearl/src/api/index.js index b4e123186d..ce12232710 100644 --- a/packages/medusa-plugin-brightpearl/src/api/index.js +++ b/packages/medusa-plugin-brightpearl/src/api/index.js @@ -1,6 +1,8 @@ import { Router } from "express" import bodyParser from "body-parser" +const BP_SECRET_TOKEN = process.env.BP_SECRET_TOKEN || "" + export default (container) => { const app = Router() @@ -40,5 +42,35 @@ export default (container) => { } ) + app.post("/brightpearl/orders/:id", async (req, res) => { + const { access_token } = req.query + const { id } = req.params + + if ( + !access_token || + !id || + !BP_SECRET_TOKEN || + access_token !== BP_SECRET_TOKEN + ) { + res.sendStatus(401) + return + } + + const brightpearlService = req.scope.resolve("brightpearlService") + const orderService = req.scope.resolve("orderService") + + try { + const order = await orderService.retrieve(id) + if (order.metadata && order.metadata.brightpearl_sales_order_id) { + throw new Error("Already sent to BP") + } + + await brightpearlService.createSalesOrder(order) + res.sendStatus(200) + } catch (err) { + res.status(400).json(err) + } + }) + return app } diff --git a/packages/medusa-plugin-brightpearl/src/services/__tests__/brightpearl.js b/packages/medusa-plugin-brightpearl/src/services/__tests__/brightpearl.js new file mode 100644 index 0000000000..45bac6472a --- /dev/null +++ b/packages/medusa-plugin-brightpearl/src/services/__tests__/brightpearl.js @@ -0,0 +1,155 @@ +import BrightpearlService from "../brightpearl" +import Brightpearl, { mockCreateOrder } from "../../utils/brightpearl" + +jest.mock("../../utils/brightpearl") + +const OrderService = { + setMetadata: () => { + return Promise.resolve() + }, +} + +const TotalsService = { + getTotal: () => { + return Promise.resolve(123) + }, + getLineDiscounts: () => { + return Promise.resolve([]) + }, + getShippingTotal: () => { + return 123.9999929393293 + }, + rounded: (value) => { + const decimalPlaces = 4 + return Number( + Math.round(parseFloat(value + "e" + decimalPlaces)) + "e-" + decimalPlaces + ) + }, +} + +const OAuthService = { + retrieveByName: () => { + return Promise.resolve({ + data: { + access_token: "12345", + }, + }) + }, +} + +const RegionService = { + retrieve: () => { + return Promise.resolve({ + tax_code: "1234", + }) + }, +} + +describe("BrightpearlService", () => { + describe("createSalesOrder", () => { + const order = { + items: [ + { + title: "Test", + content: { + variant: { + sku: "TEST", + }, + unit_price: 11, + }, + quantity: 2, + }, + ], + shipping_methods: [ + { + name: "standard", + price: 123.9999929393293, + }, + ], + payment_method: { + _id: "123", + }, + tax_rate: 0.231, + currency_code: "DKK", + display_id: "1234", + _id: "12355", + discounts: [], + shipping_address: { + first_name: "Test", + last_name: "Testson", + address_1: "Test", + address_2: "TEst", + postal_code: "1234", + country_code: "DK", + phone: "12345678", + }, + email: "test@example.com", + } + + const bpService = new BrightpearlService( + { + orderService: OrderService, + totalsService: TotalsService, + oauthService: OAuthService, + regionService: RegionService, + }, + { account: "test" } + ) + + it("successfully builds sales order", async () => { + await bpService.createSalesOrder(order) + + expect(mockCreateOrder).toHaveBeenCalledWith({ + currency: { code: "DKK" }, + ref: "1234", + externalRef: "12355", + channelId: "1", + installedIntegrationInstanceId: undefined, + statusId: "3", + customer: { + id: "12345", + address: { + addressFullName: "Test Testson", + addressLine1: "Test", + addressLine2: "TEst", + postalCode: "1234", + countryIsoCode: "DK", + telephone: "12345678", + email: "test@example.com", + }, + }, + delivery: { + shippingMethodId: 0, + address: { + addressFullName: "Test Testson", + addressLine1: "Test", + addressLine2: "TEst", + postalCode: "1234", + countryIsoCode: "DK", + telephone: "12345678", + email: "test@example.com", + }, + }, + rows: [ + { + name: "Test", + net: 22, + tax: 5.082, + quantity: 2, + taxCode: "1234", + externalRef: undefined, + nominalCode: "4000", + }, + { + name: "Shipping: standard", + quantity: 1, + net: 124, + tax: 28.644, + taxCode: "1234", + nominalCode: "4040", + }, + ], + }) + }) + }) +}) diff --git a/packages/medusa-plugin-brightpearl/src/services/brightpearl.js b/packages/medusa-plugin-brightpearl/src/services/brightpearl.js index 33ac4cc568..26a970eda5 100644 --- a/packages/medusa-plugin-brightpearl/src/services/brightpearl.js +++ b/packages/medusa-plugin-brightpearl/src/services/brightpearl.js @@ -279,9 +279,12 @@ class BrightpearlService extends BaseService { name: `${fromRefund.reason}: ${fromRefund.note}`, quantity: 1, taxCode: region.tax_code, - net: fromRefund.amount / (1 + fromOrder.tax_rate), - tax: - fromRefund.amount - fromRefund.amount / (1 + fromOrder.tax_rate), + net: this.totalsService_.rounded( + fromRefund.amount / (1 + fromOrder.tax_rate) + ), + tax: this.totalsService_.rounded( + fromRefund.amount - fromRefund.amount / (1 + fromOrder.tax_rate) + ), nominalCode: accountingCode, }, ], @@ -339,8 +342,12 @@ class BrightpearlService extends BaseService { return row.externalRef === i.item_id }) return { - net: (parentRow.net / parentRow.quantity) * i.quantity, - tax: (parentRow.tax / parentRow.quantity) * i.quantity, + net: this.totalsService_.rounded( + (parentRow.net / parentRow.quantity) * i.quantity + ), + tax: this.totalsService_.rounded( + (parentRow.tax / parentRow.quantity) * i.quantity + ), productId: parentRow.productId, taxCode: parentRow.taxCode, externalRef: parentRow.externalRef, @@ -360,8 +367,12 @@ class BrightpearlService extends BaseService { name: "Difference", quantity: 1, taxCode: region.tax_code, - net: difference / (1 + fromOrder.tax_rate), - tax: difference - difference / (1 + fromOrder.tax_rate), + net: this.totalsService_.rounded( + difference / (1 + fromOrder.tax_rate) + ), + tax: this.totalsService_.rounded( + difference - difference / (1 + fromOrder.tax_rate) + ), nominalCode: this.options.sales_account_code || "4000", }) } @@ -543,8 +554,10 @@ class BrightpearlService extends BaseService { } else { row.name = item.title } - row.net = item.content.unit_price * item.quantity - discount.amount - row.tax = row.net * fromOrder.tax_rate + row.net = this.totalsService_.rounded( + item.content.unit_price * item.quantity - discount.amount + ) + row.tax = this.totalsService_.rounded(row.net * fromOrder.tax_rate) row.quantity = item.quantity row.taxCode = region.tax_code row.externalRef = item._id @@ -560,8 +573,8 @@ class BrightpearlService extends BaseService { lines.push({ name: `Shipping: ${shippingMethods.map((m) => m.name).join(" + ")}`, quantity: 1, - net: shippingTotal, - tax: shippingTotal * fromOrder.tax_rate, + net: this.totalsService_.rounded(shippingTotal), + tax: this.totalsService_.rounded(shippingTotal * fromOrder.tax_rate), taxCode: region.tax_code, nominalCode: this.options.shipping_account_code || "4040", }) diff --git a/packages/medusa-plugin-brightpearl/src/services/oauth.js b/packages/medusa-plugin-brightpearl/src/services/oauth.js index 6aecc55bd6..5094a32e7d 100644 --- a/packages/medusa-plugin-brightpearl/src/services/oauth.js +++ b/packages/medusa-plugin-brightpearl/src/services/oauth.js @@ -15,8 +15,7 @@ class BrightpearlOauth extends OauthService { const client_id = "medusa-dev" const client_secret = CLIENT_SECRET const state = randomize("A0", 16) - const redirect = - "https://tekla-staging-admin.medusa-commerce.com/a/oauth/brightpearl" + const redirect = "https://tekla.medusa-commerce.com/a/oauth/brightpearl" return { application_name: "brightpearl", display_name: "Brightpearl", @@ -40,8 +39,7 @@ class BrightpearlOauth extends OauthService { const params = { client_id: "medusa-dev", client_secret: CLIENT_SECRET, - redirect: - "https://tekla-staging-admin.medusa-commerce.com/a/oauth/brightpearl", + redirect: "https://tekla.medusa-commerce.com/a/oauth/brightpearl", code, } diff --git a/packages/medusa-plugin-brightpearl/src/utils/__mocks__/brightpearl.js b/packages/medusa-plugin-brightpearl/src/utils/__mocks__/brightpearl.js new file mode 100644 index 0000000000..ac9446c4c2 --- /dev/null +++ b/packages/medusa-plugin-brightpearl/src/utils/__mocks__/brightpearl.js @@ -0,0 +1,37 @@ +export const mockCreateOrder = jest + .fn() + .mockReturnValue(Promise.resolve("1234")) + +const mock = jest.fn().mockImplementation(() => { + return { + warehouses: { + createReservation: jest.fn().mockReturnValue(Promise.resolve()), + }, + payments: { + create: jest.fn().mockReturnValue(Promise.resolve()), + }, + orders: { + create: mockCreateOrder, + retrieve: jest.fn().mockReturnValue(Promise.resolve()), + }, + products: { + retrieveBySKU: jest.fn().mockReturnValue( + Promise.resolve({ + productId: 1234, + }) + ), + }, + customers: { + retrieveByEmail: jest.fn().mockReturnValue( + Promise.resolve([ + { + primaryEmail: "test@example.com", + contactId: "12345", + }, + ]) + ), + }, + } +}) + +export default mock diff --git a/packages/medusa-plugin-brightpearl/src/utils/brightpearl.js b/packages/medusa-plugin-brightpearl/src/utils/brightpearl.js index 136f5db885..05e904dc38 100644 --- a/packages/medusa-plugin-brightpearl/src/utils/brightpearl.js +++ b/packages/medusa-plugin-brightpearl/src/utils/brightpearl.js @@ -93,7 +93,6 @@ class BrightpearlClient { this.client_.interceptors.response.use(undefined, async (error) => { const response = error.response - console.log(response.data && response.data.errors) if (response) { if ( @@ -104,7 +103,6 @@ class BrightpearlClient { try { await onRefresh(this) } catch (authError) { - console.log(authError) // refreshing has failed, but report the original error, i.e. 401 return Promise.reject(error) } diff --git a/packages/medusa-plugin-brightpearl/utils/brightpearl.js b/packages/medusa-plugin-brightpearl/utils/brightpearl.js index ded96e3cfb..1056f7cc40 100644 --- a/packages/medusa-plugin-brightpearl/utils/brightpearl.js +++ b/packages/medusa-plugin-brightpearl/utils/brightpearl.js @@ -355,47 +355,44 @@ var BrightpearlClient = /*#__PURE__*/function () { switch (_context.prev = _context.next) { case 0: response = error.response; - console.log(response.data && response.data.errors); if (!response) { - _context.next = 15; + _context.next = 13; break; } if (!(response.status === 401 && error.config && !error.config.__isRetryRequest)) { - _context.next = 15; + _context.next = 13; break; } - _context.prev = 4; - _context.next = 7; + _context.prev = 3; + _context.next = 6; return onRefresh(_this2); - case 7: - _context.next = 13; + case 6: + _context.next = 11; break; - case 9: - _context.prev = 9; - _context.t0 = _context["catch"](4); - console.log(_context.t0); // refreshing has failed, but report the original error, i.e. 401 - + case 8: + _context.prev = 8; + _context.t0 = _context["catch"](3); return _context.abrupt("return", Promise.reject(error)); - case 13: + case 11: // retry the original request error.config.__isRetryRequest = true; return _context.abrupt("return", _this2.client_(error.config)); - case 15: + case 13: return _context.abrupt("return", Promise.reject(error)); - case 16: + case 14: case "end": return _context.stop(); } } - }, _callee, null, [[4, 9]]); + }, _callee, null, [[3, 8]]); })); return function (_x) { diff --git a/packages/medusa-plugin-ip-lookup/package.json b/packages/medusa-plugin-ip-lookup/package.json index d28eab3ccc..554496759e 100644 --- a/packages/medusa-plugin-ip-lookup/package.json +++ b/packages/medusa-plugin-ip-lookup/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-ip-lookup", - "version": "1.0.0-alpha.26", + "version": "1.0.0-y.24", "description": "IP lookup middleware for Medusa core", "main": "dist/index.js", "repository": { diff --git a/packages/medusa-plugin-ip-lookup/src/api/medusa-middleware.js b/packages/medusa-plugin-ip-lookup/src/api/medusa-middleware.js index 4a26b1ee56..e1fa879856 100644 --- a/packages/medusa-plugin-ip-lookup/src/api/medusa-middleware.js +++ b/packages/medusa-plugin-ip-lookup/src/api/medusa-middleware.js @@ -11,8 +11,12 @@ export default { const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress + console.log(ip) + const { data } = await ipLookupService.lookupIp(ip) + console.log(data) + if (!data.country_code) { next() return @@ -23,6 +27,8 @@ export default { countries: data.country_code, }) + console.log(regions) + // If this region exists, add it to the body of the cart creation request if (regions[0]) { req.body.region_id = regions[0]._id.toString() @@ -30,6 +36,7 @@ export default { next() } catch (error) { + console.log(error) next() } },