* feat: Add DiscountCondition entity + Join table per relation (#1146) * feat: Convert DiscountService to TypeScript (#1149) * feat: Add DiscountRepository + bulk insert and remove (#1156) * feat: Add `conditions` to payload in `POST /discounts` and `POST /discounts/:id` (#1170) * feat: Add DiscountRuleCondition entity * fix relation * fix join key * Add discount rule condition repo * add join table per relation * Convert DiscountService to TypeScript * feat: Add DiscountConditionRepository * Add migration + remove use of valid_for * revert changes to files, not done yet * init work on create discount endpoint * Add conditions to create discount endpoint * Add conditions to update discount endpoint * Add unique constraint to discount condition * integration tests passing * fix imports of models * fix tests (excluding totals calculations) * Fix commented code * add unique constraint on discount condition * Add generic way of generating retrieve configs * Requested changes + ExactlyOne validator * Remove isLocal flag from error handler * Use postgres error constant * remove commented code * feat: Add `isValidForProduct` to check if Discount is valid for a given Product (#1172) * feat: Add `canApplyForCustomer` to check if Discount is valid for customer groups (#1212) * feat: Add `calculateDiscountForLineItem` (#1224) * feat: Adds discount condition test factory (#1228) * Remove use of valid_for * Tests passing * Remove valid_for form relations * Add integration tests for applying discounts to cart
333 lines
8.6 KiB
JavaScript
333 lines
8.6 KiB
JavaScript
class OrderSubscriber {
|
|
constructor({
|
|
segmentService,
|
|
eventBusService,
|
|
orderService,
|
|
cartService,
|
|
claimService,
|
|
returnService,
|
|
fulfillmentService,
|
|
}) {
|
|
this.orderService_ = orderService
|
|
|
|
this.cartService_ = cartService
|
|
|
|
this.returnService_ = returnService
|
|
|
|
this.claimService_ = claimService
|
|
|
|
this.fulfillmentService_ = fulfillmentService
|
|
|
|
// Swaps
|
|
// swap.created
|
|
// swap.received
|
|
// swap.shipment_created
|
|
// swap.payment_completed
|
|
// swap.payment_captured
|
|
// swap.refund_processed
|
|
|
|
eventBusService.subscribe(
|
|
"order.shipment_created",
|
|
async ({ id, fulfillment_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",
|
|
"discounts.rule",
|
|
"shipping_methods",
|
|
"payments",
|
|
"fulfillments",
|
|
"returns",
|
|
"items",
|
|
"gift_cards",
|
|
"gift_card_transactions",
|
|
"swaps",
|
|
"swaps.return_order",
|
|
"swaps.payment",
|
|
"swaps.shipping_methods",
|
|
"swaps.shipping_address",
|
|
"swaps.additional_items",
|
|
"swaps.fulfillments",
|
|
],
|
|
})
|
|
|
|
const fulfillment = await this.fulfillmentService_.retrieve(
|
|
fulfillment_id,
|
|
{
|
|
relations: ["items"],
|
|
}
|
|
)
|
|
|
|
const toBuildFrom = {
|
|
...order,
|
|
provider_id: fulfillment.provider,
|
|
items: fulfillment.items.map((i) =>
|
|
order.items.find((l) => l.id === i.item_id)
|
|
),
|
|
}
|
|
|
|
const orderData = await segmentService.buildOrder(toBuildFrom)
|
|
const orderEvent = {
|
|
event: "Order Shipped",
|
|
userId: order.customer_id,
|
|
properties: orderData,
|
|
timestamp: fulfillment.shipped_at,
|
|
}
|
|
|
|
segmentService.track(orderEvent)
|
|
}
|
|
)
|
|
|
|
eventBusService.subscribe("claim.created", async ({ id }) => {
|
|
const claim = await this.claimService_.retrieve(id, {
|
|
relations: [
|
|
"order",
|
|
"claim_items",
|
|
"claim_items.item",
|
|
"claim_items.tags",
|
|
"claim_items.variant",
|
|
],
|
|
})
|
|
|
|
for (const ci of claim.claim_items) {
|
|
const price = ci.item.unit_price / 100
|
|
const reporting_price = await segmentService.getReportingValue(
|
|
claim.order.currency_code,
|
|
price
|
|
)
|
|
const event = {
|
|
event: "Item Claimed",
|
|
userId: claim.order.customer_id,
|
|
timestamp: claim.created_at,
|
|
properties: {
|
|
price,
|
|
reporting_price,
|
|
order_id: claim.order_id,
|
|
claim_id: claim.id,
|
|
claim_item_id: ci.id,
|
|
type: claim.type,
|
|
quantity: ci.quantity,
|
|
variant: ci.variant.sku,
|
|
product_id: ci.variant.product_id,
|
|
reason: ci.reason,
|
|
note: ci.note,
|
|
tags: ci.tags.map((t) => ({ id: t.id, value: t.value })),
|
|
},
|
|
}
|
|
await segmentService.track(event)
|
|
}
|
|
})
|
|
|
|
eventBusService.subscribe(
|
|
"order.items_returned",
|
|
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",
|
|
"discounts.rule",
|
|
"shipping_methods",
|
|
"payments",
|
|
"fulfillments",
|
|
"returns",
|
|
"items",
|
|
"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, {
|
|
relations: ["items", "items.reason"],
|
|
})
|
|
|
|
const shipping = []
|
|
if (ret.shipping_method && ret.shipping_method.price) {
|
|
shipping.push({
|
|
...ret.shipping_method,
|
|
price: -1 * (ret.shipping_method.price / 100),
|
|
})
|
|
}
|
|
|
|
let merged = [...order.items]
|
|
|
|
// merge items from order with items from order swaps
|
|
if (order.swaps && order.swaps.length) {
|
|
for (const s of order.swaps) {
|
|
merged = [...merged, ...s.additional_items]
|
|
}
|
|
}
|
|
|
|
const toBuildFrom = {
|
|
...order,
|
|
shipping_methods: shipping,
|
|
items: ret.items.map((i) => {
|
|
const li = merged.find((l) => l.id === i.item_id)
|
|
if (i.reason) {
|
|
li.reason = i.reason
|
|
}
|
|
|
|
if (i.note) {
|
|
li.note = i.note
|
|
}
|
|
return li
|
|
}),
|
|
}
|
|
|
|
const orderData = await segmentService.buildOrder(toBuildFrom)
|
|
const orderEvent = {
|
|
event: "Order Refunded",
|
|
userId: order.customer_id,
|
|
properties: orderData,
|
|
timestamp: new Date(),
|
|
}
|
|
|
|
segmentService.track(orderEvent)
|
|
}
|
|
)
|
|
|
|
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 = {
|
|
event: "Order Cancelled",
|
|
userId: order.customer_id,
|
|
properties: orderData,
|
|
timestamp: date,
|
|
}
|
|
|
|
segmentService.track(orderEvent)
|
|
})
|
|
|
|
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",
|
|
"discounts.rule",
|
|
"shipping_methods",
|
|
"payments",
|
|
"fulfillments",
|
|
"items",
|
|
"returns",
|
|
"gift_cards",
|
|
"gift_card_transactions",
|
|
"swaps",
|
|
"swaps.return_order",
|
|
"swaps.payment",
|
|
"swaps.shipping_methods",
|
|
"swaps.shipping_address",
|
|
"swaps.additional_items",
|
|
"swaps.fulfillments",
|
|
],
|
|
})
|
|
|
|
const eventContext = {}
|
|
const integrations = {}
|
|
|
|
if (order.cart_id) {
|
|
try {
|
|
const cart = await this.cartService_.retrieve(order.cart_id, {
|
|
select: ["context"],
|
|
})
|
|
|
|
if (cart.context) {
|
|
if (cart.context.ip) {
|
|
eventContext.ip = cart.context.ip
|
|
}
|
|
|
|
if (cart.context.user_agent) {
|
|
eventContext.user_agent = cart.context.user_agent
|
|
}
|
|
|
|
if (segmentService.options_ && segmentService.options_.use_ga_id) {
|
|
if (cart.context.ga_id) {
|
|
integrations["Google Analytics"] = {
|
|
clientId: cart.context.ga_id,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.log(err)
|
|
console.warn("Failed to gather context for order")
|
|
}
|
|
}
|
|
|
|
const orderData = await segmentService.buildOrder(order)
|
|
const orderEvent = {
|
|
event: "Order Completed",
|
|
userId: order.customer_id,
|
|
properties: orderData,
|
|
timestamp: order.created_at,
|
|
context: eventContext,
|
|
integrations,
|
|
}
|
|
|
|
segmentService.identify({
|
|
userId: order.customer_id,
|
|
traits: {
|
|
email: order.email,
|
|
firstName: order.shipping_address.first_name,
|
|
lastName: order.shipping_address.last_name,
|
|
},
|
|
})
|
|
|
|
segmentService.track(orderEvent)
|
|
})
|
|
}
|
|
}
|
|
|
|
export default OrderSubscriber
|