UNPKG

@medusajs/order

Version:
1,104 lines (1,103 loc) • 107 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); const types_1 = require("@medusajs/framework/types"); const utils_1 = require("@medusajs/framework/utils"); const core_1 = require("@mikro-orm/core"); const _models_1 = require("../models"); const joiner_config_1 = require("../joiner-config"); const utils_2 = require("../utils"); const BundledActions = __importStar(require("./actions")); const generateMethodForModels = { Order: _models_1.Order, OrderAddress: _models_1.OrderAddress, OrderLineItem: _models_1.OrderLineItem, OrderLineItemAdjustment: _models_1.OrderLineItemAdjustment, OrderLineItemTaxLine: _models_1.OrderLineItemTaxLine, OrderShippingMethod: _models_1.OrderShippingMethod, OrderShippingMethodAdjustment: _models_1.OrderShippingMethodAdjustment, OrderShippingMethodTaxLine: _models_1.OrderShippingMethodTaxLine, OrderTransaction: _models_1.OrderTransaction, OrderChange: _models_1.OrderChange, OrderChangeAction: _models_1.OrderChangeAction, OrderItem: _models_1.OrderItem, OrderSummary: _models_1.OrderSummary, OrderShipping: _models_1.OrderShipping, ReturnReason: _models_1.ReturnReason, Return: _models_1.Return, ReturnItem: _models_1.ReturnItem, OrderClaim: _models_1.OrderClaim, OrderClaimItem: _models_1.OrderClaimItem, OrderClaimItemImage: _models_1.OrderClaimItemImage, OrderExchange: _models_1.OrderExchange, OrderExchangeItem: _models_1.OrderExchangeItem, OrderCreditLine: _models_1.OrderCreditLine, }; { const MikroORMEntity = (0, utils_1.toMikroORMEntity)(_models_1.OrderChangeAction); MikroORMEntity.prototype["onInit_OrderChangeAction"] = function () { this.version ??= this.order_change?.version ?? null; this.order_id ??= this.order_change?.order_id ?? null; this.claim_id ??= this.order_change?.claim_id ?? null; this.exchange_id ??= this.order_change?.exchange_id ?? null; if (!this.claim_id && !this.exchange_id) { this.return_id = this.return?.id ?? this.order_change?.return_id ?? null; } }; (0, core_1.OnInit)()(MikroORMEntity.prototype, "onInit_OrderChangeAction"); (0, core_1.BeforeCreate)()(MikroORMEntity.prototype, "onInit_OrderChangeAction"); } { const MikroORMEntity = (0, utils_1.toMikroORMEntity)(_models_1.OrderShipping); MikroORMEntity.prototype["onInit_OrderShipping"] = function () { this.version ??= this.order?.version ?? null; this.order ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.Order), this.order?.id ?? null); this.return ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.Return), this.return?.id ?? null); this.claim ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.OrderClaim), this.claim?.id ?? null); this.exchange ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.OrderExchange), this.exchange?.id ?? null); this.shipping_method ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.OrderShippingMethod), this.shipping_method?.id ?? null); }; (0, core_1.OnInit)()(MikroORMEntity.prototype, "onInit_OrderShipping"); (0, core_1.BeforeCreate)()(MikroORMEntity.prototype, "onInit_OrderShipping"); } { const MikroORMEntity = (0, utils_1.toMikroORMEntity)(_models_1.OrderItem); MikroORMEntity.prototype["onInit_OrderItem"] = function () { this.version ??= this.order?.version ?? null; this.order ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.Order), this.order?.id ?? null); this.item ??= (0, core_1.rel)((0, utils_1.toMikroORMEntity)(_models_1.OrderLineItem), this.item?.id ?? null); }; (0, core_1.OnInit)()(MikroORMEntity.prototype, "onInit_OrderItem"); (0, core_1.BeforeCreate)()(MikroORMEntity.prototype, "onInit_OrderItem"); } // TODO: rm template args here, keep it for later to not collide with carlos work at least as little as possible class OrderModuleService extends utils_1.ModulesSdkUtils.MedusaService(generateMethodForModels) { constructor({ baseRepository, orderService, orderAddressService, orderLineItemService, orderShippingMethodAdjustmentService, orderShippingMethodService, orderLineItemAdjustmentService, orderShippingMethodTaxLineService, orderLineItemTaxLineService, orderTransactionService, orderChangeService, orderChangeActionService, orderItemService, orderSummaryService, orderShippingService, returnReasonService, returnService, returnItemService, orderClaimService, orderExchangeService, orderCreditLineService, }, moduleDeclaration) { // @ts-ignore super(...arguments); this.moduleDeclaration = moduleDeclaration; this.baseRepository_ = baseRepository; this.orderService_ = orderService; this.orderAddressService_ = orderAddressService; this.orderLineItemService_ = orderLineItemService; this.orderShippingMethodAdjustmentService_ = orderShippingMethodAdjustmentService; this.orderShippingMethodService_ = orderShippingMethodService; this.orderLineItemAdjustmentService_ = orderLineItemAdjustmentService; this.orderShippingMethodTaxLineService_ = orderShippingMethodTaxLineService; this.orderLineItemTaxLineService_ = orderLineItemTaxLineService; this.orderTransactionService_ = orderTransactionService; this.orderChangeService_ = orderChangeService; this.orderChangeActionService_ = orderChangeActionService; this.orderItemService_ = orderItemService; this.orderSummaryService_ = orderSummaryService; this.orderShippingService_ = orderShippingService; this.returnReasonService_ = returnReasonService; this.returnService_ = returnService; this.returnItemService_ = returnItemService; this.orderClaimService_ = orderClaimService; this.orderExchangeService_ = orderExchangeService; this.orderCreditLineService_ = orderCreditLineService; } __joinerConfig() { return joiner_config_1.joinerConfig; } shouldIncludeTotals(config) { const totalFields = [ "total", "subtotal", "tax_total", "discount_total", "discount_tax_total", "original_total", "original_tax_total", "item_total", "item_subtotal", "item_tax_total", "original_item_total", "original_item_subtotal", "original_item_tax_total", "shipping_total", "shipping_subtotal", "shipping_tax_total", "original_shipping_tax_total", "original_shipping_subtotal", "original_shipping_total", "credit_line_total", "credit_line_tax_total", "credit_line_subtotal", ]; const includeTotals = (config?.select ?? []).some((field) => totalFields.includes(field)); if (includeTotals) { this.addRelationsToCalculateTotals(config, totalFields); } return includeTotals; } addRelationsToCalculateTotals(config, totalFields) { config.relations ??= []; config.select ??= []; const requiredRelationsForTotals = [ "credit_lines", "items", "items.tax_lines", "items.adjustments", "shipping_methods", "shipping_methods.tax_lines", "shipping_methods.adjustments", ]; config.relations = (0, utils_1.deduplicate)([ ...config.relations, ...requiredRelationsForTotals, ]); config.select = config.select.filter((field) => { return (!requiredRelationsForTotals.some((val) => val.startsWith(field)) && !totalFields.includes(field)); }); } // @ts-expect-error async retrieveOrder(id, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const order = await super.retrieveOrder(id, config, sharedContext); const orderChange = await this.getActiveOrderChange_(order.id, false, sharedContext); order.order_change = orderChange; return (0, utils_2.formatOrder)(order, { entity: _models_1.Order, includeTotals, }); } // @ts-expect-error async listOrders(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const orders = await super.listOrders(filters, config, sharedContext); return (0, utils_2.formatOrder)(orders, { entity: _models_1.Order, includeTotals, }); } // @ts-expect-error async listAndCountOrders(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const [orders, count] = await super.listAndCountOrders(filters, config, sharedContext); return [ (0, utils_2.formatOrder)(orders, { entity: _models_1.Order, includeTotals, }), count, ]; } // @ts-ignore async retrieveReturn(id, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrder = await super.retrieveReturn(id, config, sharedContext); return (0, utils_2.formatOrder)(returnOrder, { entity: _models_1.Return, includeTotals, }); } // @ts-ignore async listReturns(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrders = await super.listReturns(filters, config, sharedContext); return (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.Return, includeTotals, }); } // @ts-ignore async listAndCountReturns(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const [returnOrders, count] = await super.listAndCountReturns(filters, config, sharedContext); return [ (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.Return, includeTotals, }), count, ]; } // @ts-ignore async retrieveOrderClaim(id, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrder = await super.retrieveOrderClaim(id, config, sharedContext); return (0, utils_2.formatOrder)(returnOrder, { entity: _models_1.OrderClaim, includeTotals, }); } // @ts-ignore async listOrderClaims(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrders = await super.listOrderClaims(filters, config, sharedContext); return (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.OrderClaim, includeTotals, }); } // @ts-ignore async listAndCountOrderClaims(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const [returnOrders, count] = await super.listAndCountOrderClaims(filters, config, sharedContext); return [ (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.OrderClaim, includeTotals, }), count, ]; } // @ts-ignore async retrieveOrderExchange(id, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrder = await super.retrieveOrderExchange(id, config, sharedContext); return (0, utils_2.formatOrder)(returnOrder, { entity: _models_1.OrderExchange, includeTotals, }); } // @ts-ignore async listOrderExchanges(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const returnOrders = await super.listOrderExchanges(filters, config, sharedContext); return (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.OrderExchange, includeTotals, }); } // @ts-ignore async listAndCountOrderExchanges(filters, config, sharedContext) { config ??= {}; const includeTotals = this.shouldIncludeTotals(config); const [returnOrders, count] = await super.listAndCountOrderExchanges(filters, config, sharedContext); return [ (0, utils_2.formatOrder)(returnOrders, { entity: _models_1.OrderExchange, includeTotals, }), count, ]; } // @ts-expect-error async createOrders(data, sharedContext = {}) { const input = Array.isArray(data) ? data : [data]; const orders = await this.createOrders_(input, sharedContext); const result = await this.listOrders({ id: orders.map((p) => p.id), }, { relations: [ "shipping_address", "billing_address", "summary", "items", "credit_lines", "items.tax_lines", "items.adjustments", "shipping_methods", "shipping_methods.tax_lines", "shipping_methods.adjustments", "transactions", ], }, sharedContext); return (Array.isArray(data) ? result : result[0]); } async createOrders_(data, sharedContext = {}) { await this.createOrderAddresses_(data, sharedContext); const lineItemsToCreate = []; const creditLinesToCreate = []; const createdOrders = []; for (const { items, shipping_methods, credit_lines, shipping_address, billing_address, ...order } of data) { const ord = order; const shippingMethods = shipping_methods?.map((sm) => { return { shipping_method: { ...sm }, }; }); ord.shipping_methods = shippingMethods; const orderWithTotals = (0, utils_1.decorateCartTotals)({ ...ord, shipping_methods, items, credit_lines, }); const calculated = (0, utils_2.calculateOrderChange)({ order: orderWithTotals, actions: [], transactions: order.transactions, }); (0, utils_1.createRawPropertiesFromBigNumber)(calculated); ord.summary = { totals: calculated.summary, }; const created = await this.orderService_.create(ord, sharedContext); creditLinesToCreate.push(...(credit_lines ?? []).map((creditLine) => ({ amount: utils_1.MathBN.convert(creditLine.amount), reference: creditLine.reference, reference_id: creditLine.reference_id, metadata: creditLine.metadata, order_id: created.id, }))); createdOrders.push(created); if (items?.length) { const orderItems = items.map((item) => { return { ...item, order_id: created.id, }; }); lineItemsToCreate.push(...orderItems); } } if (lineItemsToCreate.length) { await this.createOrderLineItemsBulk_(lineItemsToCreate, sharedContext); } if (creditLinesToCreate.length) { await this.orderCreditLineService_.create(creditLinesToCreate, sharedContext); } return createdOrders; } async createOrderAddresses_(input, sharedContext = {}) { const allAddresses = []; input.forEach((inputData) => { if (inputData.billing_address) { allAddresses.push({ data: inputData.billing_address, type: "billing", source: inputData, }); } if (inputData.shipping_address) { allAddresses.push({ data: inputData.shipping_address, type: "shipping", source: inputData, }); } }); const createdAddresses = allAddresses.length ? await this.orderAddressService_.create(allAddresses.map((a) => a.data), sharedContext) : []; createdAddresses.forEach((createdAddress, index) => { const { type, source } = allAddresses[index]; if (type === "billing") { source.billing_address_id = createdAddress.id; } else if (type === "shipping") { source.shipping_address_id = createdAddress.id; } }); } // @ts-expect-error async deleteOrders(orderIds, sharedContext = {}) { const ids = Array.isArray(orderIds) ? orderIds : [orderIds]; const orders = await this.orderService_.list({ id: ids }, { select: ["id", "shipping_address_id", "billing_address_id"], }, sharedContext); const orderAddressIds = orders .map((order) => [order.shipping_address_id, order.billing_address_id]) .flat(1); const orderChanges = await this.orderChangeService_.list({ order_id: ids }, { select: ["id"] }, sharedContext); const orderChangeIds = orderChanges.map((orderChange) => orderChange.id); const orderItems = await this.orderItemService_.list({ order_id: ids }, { select: ["id", "item_id"] }, sharedContext); const lineItemIds = orderItems.map((orderItem) => orderItem.item_id); const orderShipping = await this.orderShippingService_.list({ order_id: ids }, { select: ["shipping_method_id"] }, sharedContext); const orderShippingMethodIds = orderShipping.map((orderShipping) => orderShipping.shipping_method_id); await (0, utils_1.promiseAll)([ this.orderAddressService_.delete(orderAddressIds, sharedContext), // Delete order changes & actions this.orderChangeService_.delete(orderChangeIds, sharedContext), ]); // Delete order, order items, summary, shipping methods and transactions await super.deleteOrders(ids, sharedContext); await (0, utils_1.promiseAll)([ this.orderLineItemService_.delete(lineItemIds, sharedContext), this.orderShippingMethodService_.delete(orderShippingMethodIds, sharedContext), ]); } // @ts-expect-error async updateOrders(dataOrIdOrSelector, data, sharedContext = {}) { const result = await this.updateOrders_(dataOrIdOrSelector, data, sharedContext); const serializedResult = await this.baseRepository_.serialize(result, { populate: true, }); return (0, utils_1.isString)(dataOrIdOrSelector) ? serializedResult[0] : serializedResult; } async updateOrders_(dataOrIdOrSelector, data, sharedContext = {}) { let toUpdate = []; if ((0, utils_1.isString)(dataOrIdOrSelector)) { toUpdate = [ { id: dataOrIdOrSelector, ...data, }, ]; } else if (Array.isArray(dataOrIdOrSelector)) { toUpdate = dataOrIdOrSelector; } else { const orders = await this.orderService_.list({ ...dataOrIdOrSelector }, { select: ["id"] }, sharedContext); toUpdate = orders.map((order) => { return { ...data, id: order.id, }; }); } const result = await this.orderService_.update(toUpdate, sharedContext); return result; } // @ts-expect-error async createOrderLineItems(orderIdOrData, data, sharedContext = {}) { let items = []; if ((0, utils_1.isString)(orderIdOrData)) { items = await this.createOrderLineItems_(orderIdOrData, data, sharedContext); } else { const data = Array.isArray(orderIdOrData) ? orderIdOrData : [orderIdOrData]; const allOrderIds = data.map((dt) => dt.order_id); const order = await this.listOrders({ id: allOrderIds }, { select: ["id", "version"] }, sharedContext); const mapOrderVersion = order.reduce((acc, curr) => { acc[curr.id] = curr.version; return acc; }, {}); const lineItems = data.map((dt) => { return { ...dt, version: mapOrderVersion[dt.order_id], }; }); items = await this.createOrderLineItemsBulk_(lineItems, sharedContext); } return await this.baseRepository_.serialize(items, { populate: true, }); } async createOrderLineItems_(orderId, items, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id", "version"] }, sharedContext); const toUpdate = items.map((item) => { return { ...item, order_id: order.id, version: order.version, }; }); return await this.createOrderLineItemsBulk_(toUpdate, sharedContext); } async createOrderLineItemsBulk_(data, sharedContext = {}) { const orderItemToCreate = []; const lineItems = await this.orderLineItemService_.create(data, sharedContext); for (let i = 0; i < lineItems.length; i++) { const item = lineItems[i]; const toCreate = data[i]; if (toCreate.order_id) { orderItemToCreate.push({ order_id: toCreate.order_id, version: toCreate.version ?? 1, item_id: item.id, quantity: toCreate.quantity, }); } } if (orderItemToCreate.length) { await this.orderItemService_.create(orderItemToCreate, sharedContext); } return lineItems; } // @ts-expect-error async updateOrderLineItems(lineItemIdOrDataOrSelector, data, sharedContext = {}) { let items = []; if ((0, utils_1.isString)(lineItemIdOrDataOrSelector)) { const item = await this.updateOrderLineItem_(lineItemIdOrDataOrSelector, data, sharedContext); return await this.baseRepository_.serialize(item, { populate: true, }); } const toUpdate = Array.isArray(lineItemIdOrDataOrSelector) ? lineItemIdOrDataOrSelector : [ { selector: lineItemIdOrDataOrSelector, data: data, }, ]; items = await this.updateOrderLineItemsWithSelector_(toUpdate, sharedContext); return await this.baseRepository_.serialize(items, { populate: true, }); } async updateOrderLineItem_(lineItemId, data, sharedContext = {}) { const [item] = await this.orderLineItemService_.update([{ id: lineItemId, ...data }], sharedContext); if ("quantity" in data) { await this.updateOrderItemWithSelector_([ { selector: { item_id: item.id }, data, }, ], sharedContext); } return item; } async updateOrderLineItemsWithSelector_(updates, sharedContext = {}) { let toUpdate = []; const detailsToUpdate = []; for (const { selector, data } of updates) { const items = await this.listOrderLineItems({ ...selector }, {}, sharedContext); items.forEach((item) => { toUpdate.push({ ...data, id: item.id, }); if ("quantity" in data) { detailsToUpdate.push({ selector: { item_id: item.id }, data, }); } }); } if (detailsToUpdate.length) { await this.updateOrderItemWithSelector_(detailsToUpdate, sharedContext); } return await this.orderLineItemService_.update(toUpdate, sharedContext); } async updateOrderItem(orderItemIdOrDataOrSelector, data, sharedContext = {}) { let items = []; if ((0, utils_1.isString)(orderItemIdOrDataOrSelector)) { const item = await this.updateOrderItem_(orderItemIdOrDataOrSelector, data, sharedContext); return await this.baseRepository_.serialize(item, { populate: true, }); } const toUpdate = Array.isArray(orderItemIdOrDataOrSelector) ? orderItemIdOrDataOrSelector : [ { selector: orderItemIdOrDataOrSelector, data: data, }, ]; items = await this.updateOrderItemWithSelector_(toUpdate, sharedContext); return await this.baseRepository_.serialize(items, { populate: true, }); } async updateOrderItem_(orderItemId, data, sharedContext = {}) { const [detail] = await this.orderItemService_.update([{ id: orderItemId, ...data }], sharedContext); return detail; } async updateOrderItemWithSelector_(updates, sharedContext = {}) { let toUpdate = []; for (const { selector, data } of updates) { const details = await this.listOrderItems({ ...selector }, {}, sharedContext); details.forEach((detail) => { toUpdate.push({ ...data, id: detail.id, }); }); } return await this.orderItemService_.update(toUpdate, sharedContext); } // @ts-expect-error async createOrderShippingMethods(orderIdOrData, data, sharedContext = {}) { let methods; if ((0, utils_1.isString)(orderIdOrData)) { methods = await this.createOrderShippingMethods_(orderIdOrData, data, sharedContext); } else { const data = Array.isArray(orderIdOrData) ? orderIdOrData : [orderIdOrData]; const allOrderIds = data.map((dt) => dt.order_id); const order = await this.listOrders({ id: allOrderIds }, { select: ["id", "version"] }, sharedContext); const mapOrderVersion = order.reduce((acc, curr) => { acc[curr.id] = curr.version; return acc; }, {}); const orderShippingMethodData = data.map((dt) => { return { shipping_method: dt, order_id: dt.order_id, return_id: dt.return_id, claim_id: dt.claim_id, exchange_id: dt.exchange_id, version: dt.version ?? mapOrderVersion[dt.order_id], }; }); methods = await this.createOrderShippingMethodsBulk_(orderShippingMethodData, sharedContext); } return await this.baseRepository_.serialize(methods, { populate: true }); } async createOrderShippingMethods_(orderId, data, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id", "version"] }, sharedContext); const methods = data.map((methodData) => { return { shipping_method: methodData, order_id: order.id, return_id: methodData.return_id, claim_id: methodData.claim_id, exchange_id: methodData.exchange_id, version: methodData.version ?? order.version ?? 1, }; }); return await this.createOrderShippingMethodsBulk_(methods, sharedContext); } async createOrderShippingMethodsBulk_(data, sharedContext = {}) { const sm = await this.orderShippingService_.create(data, sharedContext); return sm.map((s) => s.shipping_method); } // @ts-ignore async softDeleteOrderShippingMethods(ids, config, sharedContext) { const rel = await super.listOrderShippings({ shipping_method_id: ids, }, { select: ["id"], }, sharedContext); const orderShippingIds = rel.map((r) => r.id); const [returned] = await (0, utils_1.promiseAll)([ super.softDeleteOrderShippingMethods(ids, config, sharedContext), super.softDeleteOrderShippings(orderShippingIds, config, sharedContext), ]); return returned; } // @ts-ignore async restoreOrderShippingMethods(ids, config, sharedContext) { const rel = await super.listOrderShippings({ shipping_method_id: ids, }, { select: ["id"], }, sharedContext); const shippingIds = rel.map((r) => r.id); const [returned] = await (0, utils_1.promiseAll)([ super.restoreOrderShippingMethods(ids, config, sharedContext), super.restoreOrderShippings(shippingIds, config, sharedContext), ]); return returned; } // @ts-expect-error async createOrderLineItemAdjustments(orderIdOrData, adjustments, sharedContext = {}) { let addedAdjustments = []; if ((0, utils_1.isString)(orderIdOrData)) { const order = await this.retrieveOrder(orderIdOrData, { select: ["id"], relations: ["items.item"] }, sharedContext); const lineIds = order.items?.map((item) => item.id); for (const adj of adjustments || []) { if (!lineIds?.includes(adj.item_id)) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Line item with id ${adj.item_id} does not exist on order with id ${orderIdOrData}`); } } addedAdjustments = await this.orderLineItemAdjustmentService_.create(adjustments, sharedContext); } else { const data = Array.isArray(orderIdOrData) ? orderIdOrData : [orderIdOrData]; addedAdjustments = await this.orderLineItemAdjustmentService_.create(data, sharedContext); } return await this.baseRepository_.serialize(addedAdjustments, { populate: true, }); } async upsertOrderLineItemAdjustments(adjustments, sharedContext = {}) { let result = await this.orderLineItemAdjustmentService_.upsert(adjustments, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } async setOrderLineItemAdjustments(orderId, adjustments, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id"], relations: ["items.item.adjustments"] }, sharedContext); const existingAdjustments = (order.items ?? []) .map((item) => item.adjustments ?? []) .flat() .map((adjustment) => adjustment.id); const adjustmentsSet = new Set(adjustments .map((a) => a.id) .filter(Boolean)); const toDelete = []; // From the existing adjustments, find the ones that are not passed in adjustments existingAdjustments.forEach((adj) => { if (!adjustmentsSet.has(adj)) { toDelete.push(adj); } }); if (toDelete.length) { await this.orderLineItemAdjustmentService_.delete(toDelete, sharedContext); } let result = await this.orderLineItemAdjustmentService_.upsert(adjustments, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } async upsertOrderShippingMethodAdjustments(adjustments, sharedContext = {}) { const result = await this.orderShippingMethodAdjustmentService_.upsert(adjustments, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } async setOrderShippingMethodAdjustments(orderId, adjustments, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id"], relations: ["shipping_methods.adjustments"] }, sharedContext); const existingAdjustments = (order.shipping_methods ?? []) .map((shippingMethod) => shippingMethod.adjustments ?? []) .flat() .map((adjustment) => adjustment.id); const adjustmentsSet = new Set(adjustments .map((a) => a?.id) .filter(Boolean)); const toDelete = []; // From the existing adjustments, find the ones that are not passed in adjustments existingAdjustments.forEach((adj) => { if (!adjustmentsSet.has(adj)) { toDelete.push(adj); } }); if (toDelete.length) { await this.orderShippingMethodAdjustmentService_.delete(toDelete, sharedContext); } const result = await this.orderShippingMethodAdjustmentService_.upsert(adjustments, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } // @ts-expect-error async createOrderShippingMethodAdjustments(orderIdOrData, adjustments, sharedContext = {}) { let addedAdjustments = []; if ((0, utils_1.isString)(orderIdOrData)) { const order = await this.retrieveOrder(orderIdOrData, { select: ["id"], relations: ["shipping_methods"] }, sharedContext); const methodIds = order.shipping_methods?.map((method) => method.id); for (const adj of adjustments || []) { if (!methodIds?.includes(adj.shipping_method_id)) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Shipping method with id ${adj.shipping_method_id} does not exist on order with id ${orderIdOrData}`); } } addedAdjustments = await this.orderShippingMethodAdjustmentService_.create(adjustments, sharedContext); } else { const data = Array.isArray(orderIdOrData) ? orderIdOrData : [orderIdOrData]; addedAdjustments = await this.orderShippingMethodAdjustmentService_.create(data, sharedContext); } if ((0, utils_1.isObject)(orderIdOrData)) { return await this.baseRepository_.serialize(addedAdjustments[0], { populate: true, }); } return await this.baseRepository_.serialize(addedAdjustments, { populate: true, }); } // @ts-expect-error async createOrderLineItemTaxLines(orderIdOrData, taxLines, sharedContext = {}) { let addedTaxLines; if ((0, utils_1.isString)(orderIdOrData)) { const lines = Array.isArray(taxLines) ? taxLines : [taxLines]; addedTaxLines = await this.orderLineItemTaxLineService_.create(lines, sharedContext); } else { const data = Array.isArray(orderIdOrData) ? orderIdOrData : [orderIdOrData]; addedTaxLines = await this.orderLineItemTaxLineService_.create(data, sharedContext); } const serialized = await this.baseRepository_.serialize(addedTaxLines, { populate: true, }); if ((0, utils_1.isObject)(orderIdOrData)) { return serialized[0]; } return serialized; } async upsertOrderLineItemTaxLines(taxLines, sharedContext = {}) { const result = await this.orderLineItemTaxLineService_.upsert(taxLines, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } async setOrderLineItemTaxLines(orderId, taxLines, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id"], relations: ["items.item.tax_lines"] }, sharedContext); const existingTaxLines = (order.items ?? []) .map((item) => item.tax_lines ?? []) .flat() .map((taxLine) => taxLine.id); const taxLinesSet = new Set(taxLines .map((taxLine) => taxLine?.id) .filter(Boolean)); const toDelete = []; existingTaxLines.forEach((taxLine) => { if (!taxLinesSet.has(taxLine)) { toDelete.push(taxLine); } }); if (toDelete.length) { await this.orderLineItemTaxLineService_.delete(toDelete, sharedContext); } const result = await this.orderLineItemTaxLineService_.upsert(taxLines, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } // @ts-expect-error async createOrderShippingMethodTaxLines(orderIdOrData, taxLines, sharedContext = {}) { let addedTaxLines; if ((0, utils_1.isString)(orderIdOrData)) { const lines = Array.isArray(taxLines) ? taxLines : [taxLines]; addedTaxLines = await this.orderShippingMethodTaxLineService_.create(lines, sharedContext); } else { addedTaxLines = await this.orderShippingMethodTaxLineService_.create(taxLines, sharedContext); } const serialized = await this.baseRepository_.serialize(addedTaxLines[0], { populate: true, }); if ((0, utils_1.isObject)(orderIdOrData)) { return serialized[0]; } return serialized; } async upsertOrderShippingMethodTaxLines(taxLines, sharedContext = {}) { const result = await this.orderShippingMethodTaxLineService_.upsert(taxLines, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } async setOrderShippingMethodTaxLines(orderId, taxLines, sharedContext = {}) { const order = await this.retrieveOrder(orderId, { select: ["id"], relations: ["shipping_methods.tax_lines"] }, sharedContext); const existingTaxLines = (order.shipping_methods ?? []) .map((shippingMethod) => shippingMethod.tax_lines ?? []) .flat() .map((taxLine) => taxLine.id); const taxLinesSet = new Set(taxLines .map((taxLine) => taxLine?.id) .filter(Boolean)); const toDelete = []; existingTaxLines.forEach((taxLine) => { if (!taxLinesSet.has(taxLine)) { toDelete.push(taxLine); } }); if (toDelete.length) { await this.orderShippingMethodTaxLineService_.delete(toDelete, sharedContext); } const result = await this.orderShippingMethodTaxLineService_.upsert(taxLines, sharedContext); return await this.baseRepository_.serialize(result, { populate: true, }); } // @ts-expect-error async createReturns(data, sharedContext) { const created = await this.createOrderRelatedEntity_(data, this.returnService_, sharedContext); return await this.baseRepository_.serialize(!Array.isArray(data) ? created[0] : created, { populate: true, }); } // @ts-expect-error async createOrderClaims(data, sharedContext) { const created = await this.createOrderRelatedEntity_(data, this.orderClaimService_, sharedContext); return await this.baseRepository_.serialize(!Array.isArray(data) ? created[0] : created, { populate: true, }); } // @ts-expect-error async createOrderExchanges(data, sharedContext) { const created = await this.createOrderRelatedEntity_(data, this.orderExchangeService_, sharedContext); return await this.baseRepository_.serialize(!Array.isArray(data) ? created[0] : created, { populate: true, }); } async createOrderRelatedEntity_(data, service, sharedContext) { const data_ = Array.isArray(data) ? data : [data]; const inputDataMap = data_.reduce((acc, curr) => { acc[curr.order_id] = curr; return acc; }, {}); const orderIds = data_.map((d) => d.order_id); const orders = await this.orderService_.list({ id: orderIds }, { select: ["id", "version"] }, sharedContext); if (orders.length !== orderIds.length) { const foundOrders = orders.map((o) => o.id); const missing = orderIds.filter((id) => !foundOrders.includes(id)); throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Order could not be found: ${missing.join(", ")}`); } for (const order of orders) { inputDataMap[order.id].order_version = order.version; } return await service.create(data_, sharedContext); } async createOrderChange(data, sharedContext) { const changes = await this.createOrderChange_(data, sharedContext); return await this.baseRepository_.serialize(Array.isArray(data) ? changes : changes[0], { populate: true, }); } async createOrderChange_(data, sharedContext) { const dataArr = Array.isArray(data) ? data : [data]; const orderIds = []; const dataMap = {}; const orderChanges = await this.listOrderChanges({ order_id: dataArr.map((data) => data.order_id), status: [utils_1.OrderChangeStatus.PENDING, utils_1.OrderChangeStatus.REQUESTED], }, {}, sharedContext); const orderChangesMap = new Map(orderChanges.map((item) => [item.order_id, item])); for (const change of dataArr) { orderIds.push(change.order_id); dataMap[change.order_id] = change; } const orders = await this.orderService_.list({ id: orderIds }, { select: ["id", "version"] }, sharedContext); if (orders.length !== orderIds.length) { const foundOrders = orders.map((o) => o.id); const missing = orderIds.filter((id) => !foundOrders.includes(id)); throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Order could not be found: ${missing.join(", ")}`); } const input = orders.map((order) => { const existingOrderChange = orderChangesMap.get(order.id); if (existingOrderChange) { throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Order (${order.id}) already has an existing active order change`); } return { ...dataMap[order.id], version: order.version + 1, }; }); return await this.orderChangeService_.create(input, sharedContext); } async previewOrderChange(orderId, sharedContext) { const order = await this.retrieveOrder(orderId, { select: ["id", "version", "items.detail", "summary", "total"], relations: ["transactions", "credit_lines"], }, sharedContext); if (!order.order_change) { return order; } const orderChange = await super.retrieveOrderChange(order.order_change.id, { relations: ["actions"] }, sharedContext); const { itemsToUpsert, shippingMethodsToUpsert, calculatedOrders } = await (0, utils_2.applyChangesToOrder)([order], { [order.id]: orderChange.actions }, { addActionReferenceToObject: true }); const calculated = calculatedOrders[order.id]; await this.includeTaxLinesAndAdjustementsToPreview(calculated.order, itemsToUpsert, shippingMethodsToUpsert, sharedContext); const calcOrder = calculated.order; const orderWithTotals = (0, utils_1.decorateCartTotals)(calcOrder); calcOrder.summary = calculated.getSummaryFromOrder(orderWithTotals); (0, utils_1.createRawPropertiesFromBigNumber)(calcOrder); return calcOrder; } async includeTaxLinesAndAdjustementsToPreview(order, itemsToUpsert, shippingMethodsToUpsert, sharedContext) { const addedItems = {}; const addedShippingMethods = {}; for (const item of order.items) { const isExistingItem = item.id === item.detail?.item_id; if (!isExistingItem) { addedItems[item.id] = { ...item, quantity: item.detail?.quantity ?? item.quantity, unit_price: item.detail?.unit_price || item.unit_price, compare_at_unit_price: item.detail?.compare_at_unit_price || item.compare_at_unit_price || null, }; } } for (const sm of order.shipping_methods) { if (!(0, utils_1.isDefined)(sm.shipping_option_id)) { addedShippingMethods[sm.id] = sm; } } if (Object.keys(addedItems).length > 0) { const addedItemDetails = await this.listOrderLineItems({ id: Object.keys(addedItems) }, { relations: ["adjustments", "tax_lines"], }, sharedContext); order.items.forEach((item, idx) => { if (!addedItems[item.id]) { return; } const lineItem = addedItemDetails.find((d) => d.id === item.id); const actions = item.actions; delete item.actions; //@ts-ignore const newItem = itemsToUpsert.find((d) => d.item_id === item.id); const unitPrice = newItem?.unit_price ?? item.unit_price; const compareAtUnitPrice = newItem?.compare_at_unit_price ?? item.compare_at_unit_price; delete lineItem.raw_unit_price; delete lineItem.raw_compare_at_unit_price; order.items[idx] = { ...lineItem, actions, quantity: newItem.quantity, unit_price: unitPrice, compare_at_unit_price: compareAtUnitPrice || null, detail: { ...newItem, ...item, }, }; }); } if (Object.keys(addedShippingMethods).length > 0) { const addedShippingDetails = await this.listOrderShippingMethods({ id: Object.keys(addedShippingMethods) }, { relations: ["adjustments", "tax_lines"], }, sharedContext); order.shipping_methods.forEach((sm, idx) => { if (!addedShippingMethods[sm.id]) { return; } const shippingMethod = addedShippingDetails.find((d) => d.id === sm.id); const actions = sm.actions; delete sm.actions; const newItem = shippingMethodsToUpsert.find((d) => d.id === sm.id); sm.shipping_method_id = sm.id; delete sm.id; order.shipping_methods[idx] = { ...shippingMethod, actions, detail: { ...sm, ...newItem, }, }; }); } } async cancelOrderChange(orderChangeIdOrData, sharedContext) {