Replaces MongoDB support with PostgreSQL (#151)
- All schemas have been rewritten to a relational model - All services have been rewritten to accommodate the new data model - Adds idempotency keys to core endpoints allowing you to retry requests with no additional side effects - Adds staged jobs to avoid putting jobs in the queue when transactions abort - Adds atomic transactions to all methods with access to the data layer Co-authored-by: Oliver Windall Juhl <oliver@mrbltech.com>
This commit is contained in:
@@ -13,8 +13,8 @@ class SegmentService extends BaseService {
|
||||
constructor({ totalsService }, options) {
|
||||
super()
|
||||
|
||||
this.options_ = options
|
||||
this.totalsService_ = totalsService
|
||||
this.options_ = options
|
||||
|
||||
this.analytics_ = new Analytics(options.write_key)
|
||||
}
|
||||
@@ -30,14 +30,17 @@ class SegmentService extends BaseService {
|
||||
return this.analytics_.track(data)
|
||||
}
|
||||
|
||||
async getReportingValue(fromCurrency, value) {
|
||||
async getReportingValue(rawCurrency, value) {
|
||||
const fromCurrency = rawCurrency.toUpperCase()
|
||||
const date = "latest"
|
||||
const toCurrency =
|
||||
(this.options_.reporting_currency &&
|
||||
this.options_.reporting_currency.toUpperCase()) ||
|
||||
"EUR"
|
||||
|
||||
if (fromCurrency === toCurrency) return value.toFixed(2)
|
||||
if (fromCurrency === toCurrency) {
|
||||
return this.totalsService_.rounded(value)
|
||||
}
|
||||
|
||||
const exchangeRate = await axios
|
||||
.get(
|
||||
@@ -47,28 +50,28 @@ class SegmentService extends BaseService {
|
||||
return data.rates[fromCurrency]
|
||||
})
|
||||
|
||||
return (value / exchangeRate).toFixed(2)
|
||||
return this.totalsService_.rounded(value / exchangeRate)
|
||||
}
|
||||
|
||||
async buildOrder(order) {
|
||||
const subtotal = await this.totalsService_.getSubtotal(order)
|
||||
const total = await this.totalsService_.getTotal(order)
|
||||
const tax = await this.totalsService_.getTaxTotal(order)
|
||||
const discount = await this.totalsService_.getDiscountTotal(order)
|
||||
const shipping = await this.totalsService_.getShippingTotal(order)
|
||||
const subtotal = order.subtotal / 100
|
||||
const total = order.total / 100
|
||||
const tax = order.tax_total / 100
|
||||
const discount = order.discount_total / 100
|
||||
const shipping = order.shipping_total / 100
|
||||
const revenue = total - tax
|
||||
|
||||
let coupon
|
||||
if (order.discounts && order.discounts.length) {
|
||||
coupon = order.discounts[0].code
|
||||
coupon = order.discounts[0] && order.discounts[0].code
|
||||
}
|
||||
|
||||
const orderData = {
|
||||
checkout_id: order.cart_id,
|
||||
order_id: order._id,
|
||||
order_id: order.id,
|
||||
email: order.email,
|
||||
region_id: order.region_id,
|
||||
payment_provider: order.payment_method.provider_id,
|
||||
payment_provider: order.payments.map((p) => p.provider_id).join(","),
|
||||
shipping_methods: order.shipping_methods,
|
||||
shipping_country: order.shipping_address.country_code,
|
||||
shipping_city: order.shipping_address.city,
|
||||
@@ -102,8 +105,8 @@ class SegmentService extends BaseService {
|
||||
order.items.map(async (item) => {
|
||||
let name = item.title
|
||||
|
||||
const unit_price = item.content.unit_price
|
||||
const line_total = unit_price * item.content.quantity * item.quantity
|
||||
const unit_price = item.unit_price
|
||||
const line_total = (unit_price * item.quantity) / 100
|
||||
const revenue = await this.getReportingValue(
|
||||
order.currency_code,
|
||||
line_total
|
||||
@@ -114,11 +117,11 @@ class SegmentService extends BaseService {
|
||||
|
||||
return {
|
||||
name,
|
||||
variant: item.content.variant.sku,
|
||||
price: unit_price,
|
||||
variant,
|
||||
price: unit_price / 100,
|
||||
reporting_revenue: revenue,
|
||||
product_id: `${item.content.product._id}`,
|
||||
sku: skuParts.join("-"),
|
||||
product_id: item.variant.product_id,
|
||||
sku: item.variant.sku,
|
||||
quantity: item.quantity,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,13 +1,55 @@
|
||||
class OrderSubscriber {
|
||||
constructor({ segmentService, eventBusService }) {
|
||||
constructor({
|
||||
segmentService,
|
||||
eventBusService,
|
||||
orderService,
|
||||
returnService,
|
||||
}) {
|
||||
this.orderService_ = orderService
|
||||
|
||||
this.returnService_ = returnService
|
||||
|
||||
eventBusService.subscribe(
|
||||
"order.items_returned",
|
||||
async ({ order, return: ret }) => {
|
||||
async ({ id, return_id }) => {
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: [
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
"refunded_total",
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
],
|
||||
relations: [
|
||||
"customer",
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
"returns",
|
||||
"gift_cards",
|
||||
"gift_card_transactions",
|
||||
"swaps",
|
||||
"swaps.return_order",
|
||||
"swaps.payment",
|
||||
"swaps.shipping_methods",
|
||||
"swaps.shipping_address",
|
||||
"swaps.additional_items",
|
||||
"swaps.fulfillments",
|
||||
],
|
||||
})
|
||||
|
||||
const ret = await this.returnService_.retrieve(return_id)
|
||||
|
||||
const shipping = []
|
||||
if (ret.shipping_method && ret.shipping_method.price) {
|
||||
shipping.push({
|
||||
...ret.shipping_method,
|
||||
price: -1 * ret.shipping_method.price,
|
||||
price: -1 * (ret.shipping_method.price / 100),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,7 +57,7 @@ class OrderSubscriber {
|
||||
...order,
|
||||
shipping_methods: shipping,
|
||||
items: ret.items.map((i) =>
|
||||
order.items.find((l) => l._id === i.item_id)
|
||||
order.items.find((l) => l.id === i.item_id)
|
||||
),
|
||||
}
|
||||
|
||||
@@ -31,7 +73,19 @@ class OrderSubscriber {
|
||||
}
|
||||
)
|
||||
|
||||
eventBusService.subscribe("order.canceled", async (order) => {
|
||||
eventBusService.subscribe("order.canceled", async ({ id }) => {
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: [
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
"refunded_total",
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
],
|
||||
})
|
||||
|
||||
const date = new Date()
|
||||
const orderData = await segmentService.buildOrder(order)
|
||||
const orderEvent = {
|
||||
@@ -44,7 +98,38 @@ class OrderSubscriber {
|
||||
segmentService.track(orderEvent)
|
||||
})
|
||||
|
||||
eventBusService.subscribe("order.placed", async (order) => {
|
||||
eventBusService.subscribe("order.placed", async ({ id }) => {
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: [
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
"refunded_total",
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
],
|
||||
relations: [
|
||||
"customer",
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
"returns",
|
||||
"gift_cards",
|
||||
"gift_card_transactions",
|
||||
"swaps",
|
||||
"swaps.return_order",
|
||||
"swaps.payment",
|
||||
"swaps.shipping_methods",
|
||||
"swaps.shipping_address",
|
||||
"swaps.additional_items",
|
||||
"swaps.fulfillments",
|
||||
],
|
||||
})
|
||||
|
||||
const date = new Date(parseInt(order.created))
|
||||
const orderData = await segmentService.buildOrder(order)
|
||||
const orderEvent = {
|
||||
|
||||
Reference in New Issue
Block a user