This commit is contained in:
olivermrbl committed 2020-09-03 11:03:35 +02:00
commit 564b30ebbc
11 files changed
+273 -36

No files matched your search

+1 -1
View File
@@ -4,5 +4,5 @@
"packages/*" "packages/*"
], ],
"registry": "https://registry.npmjs.org/", "registry": "https://registry.npmjs.org/",
"version": "1.0.0-y.18" "version": "1.0.0-y.24"
} }
@@ -1,6 +1,6 @@
{ {
"name": "medusa-plugin-brightpearl", "name": "medusa-plugin-brightpearl",
"version": "1.0.0-alpha.33", "version": "1.0.0-y.23",
"description": "Brightpearl plugin for Medusa Commerce", "description": "Brightpearl plugin for Medusa Commerce",
"main": "index.js", "main": "index.js",
"repository": { "repository": {
@@ -1,6 +1,8 @@
import { Router } from "express" import { Router } from "express"
import bodyParser from "body-parser" import bodyParser from "body-parser"
const BP_SECRET_TOKEN = process.env.BP_SECRET_TOKEN || ""
export default (container) => { export default (container) => {
const app = Router() 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 return app
} }
@@ -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",
},
],
})
})
})
})
@@ -279,9 +279,12 @@ class BrightpearlService extends BaseService {
name: `${fromRefund.reason}: ${fromRefund.note}`, name: `${fromRefund.reason}: ${fromRefund.note}`,
quantity: 1, quantity: 1,
taxCode: region.tax_code, taxCode: region.tax_code,
net: fromRefund.amount / (1 + fromOrder.tax_rate), net: this.totalsService_.rounded(
tax: fromRefund.amount / (1 + fromOrder.tax_rate)
fromRefund.amount - fromRefund.amount / (1 + fromOrder.tax_rate), ),
tax: this.totalsService_.rounded(
fromRefund.amount - fromRefund.amount / (1 + fromOrder.tax_rate)
),
nominalCode: accountingCode, nominalCode: accountingCode,
}, },
], ],
@@ -339,8 +342,12 @@ class BrightpearlService extends BaseService {
return row.externalRef === i.item_id return row.externalRef === i.item_id
}) })
return { return {
net: (parentRow.net / parentRow.quantity) * i.quantity, net: this.totalsService_.rounded(
tax: (parentRow.tax / parentRow.quantity) * i.quantity, (parentRow.net / parentRow.quantity) * i.quantity
),
tax: this.totalsService_.rounded(
(parentRow.tax / parentRow.quantity) * i.quantity
),
productId: parentRow.productId, productId: parentRow.productId,
taxCode: parentRow.taxCode, taxCode: parentRow.taxCode,
externalRef: parentRow.externalRef, externalRef: parentRow.externalRef,
@@ -360,8 +367,12 @@ class BrightpearlService extends BaseService {
name: "Difference", name: "Difference",
quantity: 1, quantity: 1,
taxCode: region.tax_code, taxCode: region.tax_code,
net: difference / (1 + fromOrder.tax_rate), net: this.totalsService_.rounded(
tax: difference - difference / (1 + fromOrder.tax_rate), difference / (1 + fromOrder.tax_rate)
),
tax: this.totalsService_.rounded(
difference - difference / (1 + fromOrder.tax_rate)
),
nominalCode: this.options.sales_account_code || "4000", nominalCode: this.options.sales_account_code || "4000",
}) })
} }
@@ -543,8 +554,10 @@ class BrightpearlService extends BaseService {
} else { } else {
row.name = item.title row.name = item.title
} }
row.net = item.content.unit_price * item.quantity - discount.amount row.net = this.totalsService_.rounded(
row.tax = row.net * fromOrder.tax_rate item.content.unit_price * item.quantity - discount.amount
)
row.tax = this.totalsService_.rounded(row.net * fromOrder.tax_rate)
row.quantity = item.quantity row.quantity = item.quantity
row.taxCode = region.tax_code row.taxCode = region.tax_code
row.externalRef = item._id row.externalRef = item._id
@@ -560,8 +573,8 @@ class BrightpearlService extends BaseService {
lines.push({ lines.push({
name: `Shipping: ${shippingMethods.map((m) => m.name).join(" + ")}`, name: `Shipping: ${shippingMethods.map((m) => m.name).join(" + ")}`,
quantity: 1, quantity: 1,
net: shippingTotal, net: this.totalsService_.rounded(shippingTotal),
tax: shippingTotal * fromOrder.tax_rate, tax: this.totalsService_.rounded(shippingTotal * fromOrder.tax_rate),
taxCode: region.tax_code, taxCode: region.tax_code,
nominalCode: this.options.shipping_account_code || "4040", nominalCode: this.options.shipping_account_code || "4040",
}) })
@@ -15,8 +15,7 @@ class BrightpearlOauth extends OauthService {
const client_id = "medusa-dev" const client_id = "medusa-dev"
const client_secret = CLIENT_SECRET const client_secret = CLIENT_SECRET
const state = randomize("A0", 16) const state = randomize("A0", 16)
const redirect = const redirect = "https://tekla.medusa-commerce.com/a/oauth/brightpearl"
"https://tekla-staging-admin.medusa-commerce.com/a/oauth/brightpearl"
return { return {
application_name: "brightpearl", application_name: "brightpearl",
display_name: "Brightpearl", display_name: "Brightpearl",
@@ -40,8 +39,7 @@ class BrightpearlOauth extends OauthService {
const params = { const params = {
client_id: "medusa-dev", client_id: "medusa-dev",
client_secret: CLIENT_SECRET, client_secret: CLIENT_SECRET,
redirect: redirect: "https://tekla.medusa-commerce.com/a/oauth/brightpearl",
"https://tekla-staging-admin.medusa-commerce.com/a/oauth/brightpearl",
code, code,
} }
@@ -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
@@ -93,7 +93,6 @@ class BrightpearlClient {
this.client_.interceptors.response.use(undefined, async (error) => { this.client_.interceptors.response.use(undefined, async (error) => {
const response = error.response const response = error.response
console.log(response.data && response.data.errors)
if (response) { if (response) {
if ( if (
@@ -104,7 +103,6 @@ class BrightpearlClient {
try { try {
await onRefresh(this) await onRefresh(this)
} catch (authError) { } catch (authError) {
console.log(authError)
// refreshing has failed, but report the original error, i.e. 401 // refreshing has failed, but report the original error, i.e. 401
return Promise.reject(error) return Promise.reject(error)
} }
@@ -355,47 +355,44 @@ var BrightpearlClient = /*#__PURE__*/function () {
switch (_context.prev = _context.next) { switch (_context.prev = _context.next) {
case 0: case 0:
response = error.response; response = error.response;
console.log(response.data && response.data.errors);
if (!response) { if (!response) {
_context.next = 15; _context.next = 13;
break; break;
} }
if (!(response.status === 401 && error.config && !error.config.__isRetryRequest)) { if (!(response.status === 401 && error.config && !error.config.__isRetryRequest)) {
_context.next = 15; _context.next = 13;
break; break;
} }
_context.prev = 4; _context.prev = 3;
_context.next = 7; _context.next = 6;
return onRefresh(_this2); return onRefresh(_this2);
case 7: case 6:
_context.next = 13; _context.next = 11;
break; break;
case 9: case 8:
_context.prev = 9; _context.prev = 8;
_context.t0 = _context["catch"](4); _context.t0 = _context["catch"](3);
console.log(_context.t0); // refreshing has failed, but report the original error, i.e. 401
return _context.abrupt("return", Promise.reject(error)); return _context.abrupt("return", Promise.reject(error));
case 13: case 11:
// retry the original request // retry the original request
error.config.__isRetryRequest = true; error.config.__isRetryRequest = true;
return _context.abrupt("return", _this2.client_(error.config)); return _context.abrupt("return", _this2.client_(error.config));
case 15: case 13:
return _context.abrupt("return", Promise.reject(error)); return _context.abrupt("return", Promise.reject(error));
case 16: case 14:
case "end": case "end":
return _context.stop(); return _context.stop();
} }
} }
}, _callee, null, [[4, 9]]); }, _callee, null, [[3, 8]]);
})); }));
return function (_x) { return function (_x) {
@@ -1,6 +1,6 @@
{ {
"name": "medusa-plugin-ip-lookup", "name": "medusa-plugin-ip-lookup",
"version": "1.0.0-alpha.26", "version": "1.0.0-y.24",
"description": "IP lookup middleware for Medusa core", "description": "IP lookup middleware for Medusa core",
"main": "dist/index.js", "main": "dist/index.js",
"repository": { "repository": {
@@ -11,8 +11,12 @@ export default {
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress
console.log(ip)
const { data } = await ipLookupService.lookupIp(ip) const { data } = await ipLookupService.lookupIp(ip)
console.log(data)
if (!data.country_code) { if (!data.country_code) {
next() next()
return return
@@ -23,6 +27,8 @@ export default {
countries: data.country_code, countries: data.country_code,
}) })
console.log(regions)
// If this region exists, add it to the body of the cart creation request // If this region exists, add it to the body of the cart creation request
if (regions[0]) { if (regions[0]) {
req.body.region_id = regions[0]._id.toString() req.body.region_id = regions[0]._id.toString()
@@ -30,6 +36,7 @@ export default {
next() next()
} catch (error) { } catch (error) {
console.log(error)
next() next()
} }
}, },