Adds slack order notification
This commit is contained in:
1 parent
d4c036c29a
commit
764778b929
19 files changed
+17364
No files matched your search
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
|
"@babel/plugin-transform-instanceof",
|
||||||
|
"@babel/plugin-transform-classes"
|
||||||
|
],
|
||||||
|
"presets": ["@babel/preset-env"],
|
||||||
|
"env": {
|
||||||
|
"test": {
|
||||||
|
"plugins": ["@babel/plugin-transform-runtime"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier"],
|
||||||
|
"extends": ["prettier"],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"semi": "error",
|
||||||
|
"no-unused-expressions": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/lib
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
/*.js
|
||||||
|
!index.js
|
||||||
|
!jest.config.js
|
||||||
|
|
||||||
|
/dist
|
||||||
|
|
||||||
|
/api
|
||||||
|
/services
|
||||||
|
/models
|
||||||
|
/subscribers
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/lib
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
/*.js
|
||||||
|
!index.js
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": false,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// noop
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
testEnvironment: "node",
|
||||||
|
}
|
||||||
+11482
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "medusa-plugin-slack-notification",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Slack notifications",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/medusa-plugin-slack-notification"
|
||||||
|
},
|
||||||
|
"author": "Oliver Juhl",
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.7.5",
|
||||||
|
"@babel/core": "^7.7.5",
|
||||||
|
"@babel/node": "^7.7.4",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||||
|
"@babel/plugin-transform-instanceof": "^7.8.3",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||||
|
"@babel/preset-env": "^7.7.5",
|
||||||
|
"@babel/register": "^7.7.4",
|
||||||
|
"@babel/runtime": "^7.9.6",
|
||||||
|
"client-sessions": "^0.8.0",
|
||||||
|
"cross-env": "^5.2.1",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"jest": "^25.5.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "babel src -d .",
|
||||||
|
"prepare": "cross-env NODE_ENV=production npm run build",
|
||||||
|
"watch": "babel -w src --out-dir . --ignore **/__tests__",
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/plugin-transform-classes": "^7.9.5",
|
||||||
|
"axios": "^0.19.2",
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"medusa-core-utils": "^0.3.0",
|
||||||
|
"medusa-interfaces": "^0.3.0",
|
||||||
|
"medusa-test-utils": "^0.3.0",
|
||||||
|
"moment": "^2.27.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import hooks from "./routes/hooks"
|
||||||
|
|
||||||
|
export default (container) => {
|
||||||
|
const app = Router()
|
||||||
|
|
||||||
|
hooks(app)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export default (fn) => (...args) => fn(...args).catch(args[2])
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { default as wrap } from "./await-middleware"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
wrap,
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import bodyParser from "body-parser"
|
||||||
|
import middlewares from "../../middlewares"
|
||||||
|
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
app.use("/hooks", route)
|
||||||
|
|
||||||
|
route.post("/slack", middlewares.wrap(require("./slack").default))
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export default async (req, res) => {
|
||||||
|
try {
|
||||||
|
const slackService = req.scope.resolve("slackService")
|
||||||
|
|
||||||
|
await slackService.orderNotification("5eff28187fde3440fd15ab49")
|
||||||
|
|
||||||
|
res.sendStatus(200)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
res.status(400).send(`Webhook error: ${error.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
import moment from "moment"
|
||||||
|
import { BaseService } from "medusa-interfaces"
|
||||||
|
|
||||||
|
class SlackService extends BaseService {
|
||||||
|
/**
|
||||||
|
* @param {Object} options - options defined in `medusa-config.js`
|
||||||
|
* {
|
||||||
|
* slack_url: "https://hooks.slack.com/services/..."
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
constructor({ orderService, totalsService, regionService }, options) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.orderService_ = orderService
|
||||||
|
|
||||||
|
this.totalsService_ = totalsService
|
||||||
|
|
||||||
|
this.regionService_ = regionService
|
||||||
|
|
||||||
|
this.options_ = options
|
||||||
|
}
|
||||||
|
|
||||||
|
async orderNotification(orderId) {
|
||||||
|
const order = await this.orderService_.retrieve(orderId)
|
||||||
|
|
||||||
|
const subtotal = await this.totalsService_.getSubtotal(order)
|
||||||
|
const shippingTotal = await this.totalsService_.getShippingTotal(order)
|
||||||
|
const taxTotal = await this.totalsService_.getTaxTotal(order)
|
||||||
|
const discountTotal = await this.totalsService_.getDiscountTotal(order)
|
||||||
|
const total = await this.totalsService_.getTotal(order)
|
||||||
|
|
||||||
|
let blocks = [
|
||||||
|
{
|
||||||
|
type: "section",
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `Order *<http://localhost:8000/a/orders/${order._id}|#${order._id}>* has been processed.`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "section",
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `*Customer*\n${order.shipping_address.first_name} ${
|
||||||
|
order.shipping_address.last_name
|
||||||
|
}\n${order.email}\n*Destination*\n${
|
||||||
|
order.shipping_address.address_1
|
||||||
|
}\n${
|
||||||
|
order.shipping_address.city
|
||||||
|
}, ${order.shipping_address.country_code.toUpperCase()}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "section",
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `*Subtotal*\t${subtotal}\n*Shipping*\t${shippingTotal}\n*Discount Total*\t${discountTotal}\n*Tax*\t${taxTotal}\n*Total*\t${total}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
blocks.push({
|
||||||
|
type: "divider",
|
||||||
|
})
|
||||||
|
|
||||||
|
order.items.forEach((lineItem) => {
|
||||||
|
let line = {
|
||||||
|
type: "section",
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `*${lineItem.title}*\n${lineItem.quantity} x ${
|
||||||
|
!Array.isArray(lineItem.content) && lineItem.content.unit_price
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (lineItem.thumbnail) {
|
||||||
|
line.accessory.type = "image"
|
||||||
|
line.accessory.image_url = lineItem.thumbnail
|
||||||
|
line.accessory.alt_text = "Item"
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks.push(line)
|
||||||
|
|
||||||
|
blocks.push({
|
||||||
|
type: "divider",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return axios.post(this.options_.slack_url, {
|
||||||
|
text: `Order ${order._id} was processed`,
|
||||||
|
blocks,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SlackService
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class OrderSubscriber {
|
||||||
|
constructor({ economicService, eventBusService }) {
|
||||||
|
this.economicService_ = economicService
|
||||||
|
|
||||||
|
this.eventBus_ = eventBusService
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("order.placed", async (order) => {
|
||||||
|
await this.economicService_.draftEconomicInvoice(order)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("order.completed", async (order) => {
|
||||||
|
await this.economicService_.bookEconomicInvoice(order._id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderSubscriber
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
export default [
|
||||||
|
"BE",
|
||||||
|
"BG",
|
||||||
|
"CZ",
|
||||||
|
"DK",
|
||||||
|
"DE",
|
||||||
|
"EE",
|
||||||
|
"IE",
|
||||||
|
"EL",
|
||||||
|
"ES",
|
||||||
|
"FR",
|
||||||
|
"HR",
|
||||||
|
"IT",
|
||||||
|
"CY",
|
||||||
|
"LV",
|
||||||
|
"LT",
|
||||||
|
"LU",
|
||||||
|
"HU",
|
||||||
|
"MT",
|
||||||
|
"NL",
|
||||||
|
"AT",
|
||||||
|
"PL",
|
||||||
|
"PT",
|
||||||
|
"RO",
|
||||||
|
"SI",
|
||||||
|
"SK",
|
||||||
|
"FI",
|
||||||
|
"SE",
|
||||||
|
"UK",
|
||||||
|
]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports["default"] = void 0;
|
||||||
|
var _default = ["BE", "BG", "CZ", "DK", "DE", "EE", "IE", "EL", "ES", "FR", "HR", "IT", "CY", "LV", "LT", "LU", "HU", "MT", "NL", "AT", "PL", "PT", "RO", "SI", "SK", "FI", "SE", "UK"];
|
||||||
|
exports["default"] = _default;
|
||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user