Adds integration to send sales orders to brightpearl

This commit is contained in:
Sebastian Rindom
2020-08-03 10:23:45 +02:00
parent 630bf3abc6
commit c18677d5f2
20 changed files with 931 additions and 10 deletions
+33
View File
@@ -7,6 +7,39 @@ import errorHandler from "./middlewares/error-handler"
export default (container, config) => {
const app = Router()
app.post("/create-shipment/:order_id", async (req, res) => {
const orderService = req.scope.resolve("orderService")
const eventBus = req.scope.resolve("eventBusService")
const order = await orderService.retrieve(req.params.order_id)
await orderService.createShipment(order._id, {
item_ids: order.items.map(({ _id }) => `${_id}`),
tracking_number: "1234",
})
res.sendStatus(200)
})
app.post("/run-hook/:order_id/capture", async (req, res) => {
const orderService = req.scope.resolve("orderService")
const eventBus = req.scope.resolve("eventBusService")
const order = await orderService.retrieve(req.params.order_id)
eventBus.emit("order.payment_captured", order)
res.sendStatus(200)
})
app.post("/run-hook/:order_id", async (req, res) => {
const orderService = req.scope.resolve("orderService")
const eventBus = req.scope.resolve("eventBusService")
const order = await orderService.retrieve(req.params.order_id)
eventBus.emit("order.placed", order)
res.sendStatus(200)
})
admin(app, container, config)
store(app, container, config)
+3
View File
@@ -6,6 +6,7 @@ import PaymentMethodSchema from "./schemas/payment-method"
import ShippingMethodSchema from "./schemas/shipping-method"
import AddressSchema from "./schemas/address"
import DiscountSchema from "./schemas/discount"
import ShipmentSchema from "./schemas/shipment"
class OrderModel extends BaseModel {
static modelName = "Order"
@@ -23,6 +24,8 @@ class OrderModel extends BaseModel {
shipping_address: { type: AddressSchema, required: true },
items: { type: [LineItemSchema], required: true },
currency_code: { type: String, required: true },
tax_rate: { type: Number, required: true },
shipments: { type: [ShipmentSchema], default: [] },
region_id: { type: String, required: true },
discounts: { type: [DiscountSchema], default: [] },
customer_id: { type: String },
+1
View File
@@ -7,6 +7,7 @@ class RegionModel extends BaseModel {
name: { type: String, required: true },
currency_code: { type: String, required: true },
tax_rate: { type: Number, required: true, default: 0 },
tax_code: { type: String },
countries: { type: [String], default: [] },
payment_providers: { type: [String], default: [] },
fulfillment_providers: { type: [String], default: [] },
@@ -0,0 +1,7 @@
import mongoose from "mongoose"
export default new mongoose.Schema({
item_ids: { type: [String], required: true },
tracking_number: { type: String, default: "" },
metadata: { type: mongoose.Schema.Types.Mixed, default: {} },
})
+68 -8
View File
@@ -5,6 +5,8 @@ import { BaseService } from "medusa-interfaces"
class OrderService extends BaseService {
static Events = {
GIFT_CARD_CREATED: "order.gift_card_created",
PAYMENT_CAPTURED: "order.payment_captured",
SHIPMENT_CREATED: "order.shipment_created",
PLACED: "order.placed",
UPDATED: "order.updated",
CANCELLED: "order.cancelled",
@@ -352,6 +354,7 @@ class OrderService extends BaseService {
email: cart.email,
customer_id: cart.customer_id,
cart_id: cart._id,
tax_rate: region.tax_rate,
currency_code: region.currency_code,
}
@@ -366,6 +369,58 @@ class OrderService extends BaseService {
.then(() => this.orderModel_.findOne({ cart_id: cart._id }))
}
/**
* Adds a shipment to the order to indicate that an order has left the warehouse
*/
async createShipment(orderId, shipment) {
const order = await this.retrieve(orderId)
console.log(order)
if (order.fulfillment_status === "shipped") {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Order has already been shipped"
)
}
const shipmentSchema = Validator.object({
item_ids: Validator.array()
.items(Validator.string())
.required(),
tracking_number: Validator.string().required(),
})
const { value, error } = shipmentSchema.validate(shipment)
if (error) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Shipment not valid: ${error}`
)
}
const existing = order.shipments || []
const shipments = [...existing, value]
const allCovered = order.items.every(
i => !!shipments.find(s => s.item_ids.includes(`${i._id}`))
)
const update = {
$push: { shipments: value },
$set: {
fulfillment_status: allCovered ? "shipped" : "partially_shipped",
},
}
// Add the shipment to the order
return this.orderModel_.updateOne({ _id: orderId }, update).then(result => {
this.eventBus_.emit(OrderService.Events.SHIPMENT_CREATED, {
order_id: orderId,
shipment,
})
return result
})
}
/**
* Creates an order
* @param {object} order - the order to create
@@ -535,14 +590,19 @@ class OrderService extends BaseService {
await paymentProvider.capturePayment(data)
return this.orderModel_.updateOne(
{
_id: orderId,
},
{
$set: updateFields,
}
)
return this.orderModel_
.updateOne(
{
_id: orderId,
},
{
$set: updateFields,
}
)
.then(result => {
this.eventBus_.emit(OrderService.Events.PAYMENT_CAPTURED, result)
return result
})
}
/**
+39
View File
@@ -252,6 +252,45 @@ class TotalsService extends BaseService {
return discounts
}
async getLineDiscounts(cart, discount) {
const subtotal = this.getSubtotal(cart)
const { type, allocation, value } = discount.discount_rule
if (allocation === "total") {
let percentage = 0
if (type === "percentage") {
percentage = value / 100
} else if (type === "fixed") {
percentage = value / subtotal
}
return cart.items.map(item => {
const lineTotal = item.content.unit_price * item.quantity
return {
item,
amount: lineTotal * percentage,
}
})
} else if (allocation === "item") {
const allocationDiscounts = this.getAllocationItemDiscounts(
discount,
cart,
type
)
return cart.items.map(item => {
const discounted = allocationDiscounts.find(a =>
a.lineItem._id.equals(item._id)
)
return {
item,
amount: !!discounted ? discounted.amount : 0,
}
})
}
return cart.items.map(i => ({ item: i, amount: 0 }))
}
/**
* Calculates the total discount amount for each of the different supported
* discount types. If discounts aren't present or invalid returns 0.
+5 -1
View File
@@ -39,7 +39,11 @@ class OrderSubscriber {
})
this.eventBus_.subscribe("order.placed", async order => {
await this.cartService_.delete(order.cart_id)
await this.cartService_.delete(order.cart_id).catch(err => {
if (err.type !== "not_found") {
throw err
}
})
})
this.eventBus_.subscribe("order.placed", this.handleDiscounts)