diff --git a/.eslintignore b/.eslintignore index abe1141d33..c42969499c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,12 +2,11 @@ /packages/medusa/src/services/cart.js /packages/medusa/src/services/claim-item.js -/packages/medusa/src/services/claim.js /packages/medusa/src/services/customer.js -/packages/medusa/src/services/discount.js /packages/medusa/src/services/draft-order.js /packages/medusa/src/services/event-bus.js /packages/medusa/src/services/fulfillment.js +/packages/medusa/src/services/fulfillment-provider.js /packages/medusa/src/services/idempotency-key.js /packages/medusa/src/services/line-item.js /packages/medusa/src/services/middleware.js diff --git a/packages/medusa/src/services/claim.js b/packages/medusa/src/services/claim.js index 9d60a28626..8e73dbf83e 100644 --- a/packages/medusa/src/services/claim.js +++ b/packages/medusa/src/services/claim.js @@ -1,7 +1,5 @@ -import _ from "lodash" -import { Validator, MedusaError } from "medusa-core-utils" +import { MedusaError } from "medusa-core-utils" import { BaseService } from "medusa-interfaces" -import { Brackets } from "typeorm" class ClaimService extends BaseService { static Events = { @@ -102,7 +100,7 @@ class ClaimService extends BaseService { } update(id, data) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claimRepo = manager.getCustomRepository(this.claimRepository_) const claim = await this.retrieve(id, { relations: ["shipping_methods"] }) @@ -113,13 +111,7 @@ class ClaimService extends BaseService { ) } - const { - claim_items, - shipping_methods, - metadata, - fulfillment_status, - no_notification, - } = data + const { claim_items, shipping_methods, metadata, no_notification } = data if (metadata) { claim.metadata = this.setMetadata_(claim, metadata) @@ -183,9 +175,11 @@ class ClaimService extends BaseService { * Creates a Claim on an Order. Claims consists of items that are claimed and * optionally items to be sent as replacement for the claimed items. The * shipping address that the new items will be shipped to + * @param {Object} data - the object containing all data required to create a claim + * @return {Object} created claim */ create(data) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claimRepo = manager.getCustomRepository(this.claimRepository_) const { @@ -257,8 +251,8 @@ class ClaimService extends BaseService { let toRefund = refund_amount if (type === "refund" && typeof refund_amount === "undefined") { - const lines = claim_items.map(ci => { - const orderItem = order.items.find(oi => oi.id === ci.item_id) + const lines = claim_items.map((ci) => { + const orderItem = order.items.find((oi) => oi.id === ci.item_id) return { ...orderItem, quantity: ci.quantity, @@ -274,7 +268,7 @@ class ClaimService extends BaseService { } const newItems = await Promise.all( - additional_items.map(i => + additional_items.map((i) => this.lineItemService_ .withTransaction(manager) .generate(i.variant_id, order.region_id, i.quantity) @@ -332,7 +326,7 @@ class ClaimService extends BaseService { await this.returnService_.withTransaction(manager).create({ order_id: order.id, claim_order_id: result.id, - items: claim_items.map(ci => ({ + items: claim_items.map((ci) => ({ item_id: ci.item_id, quantity: ci.quantity, metadata: ci.metadata, @@ -362,7 +356,7 @@ class ClaimService extends BaseService { ) { const { metadata, no_notification } = config - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claim = await this.retrieve(id, { relations: [ "additional_items", @@ -429,7 +423,7 @@ class ClaimService extends BaseService { is_claim: true, no_notification: evaluatedNoNotification, }, - claim.additional_items.map(i => ({ + claim.additional_items.map((i) => ({ item_id: i.id, quantity: i.quantity, })), @@ -445,7 +439,7 @@ class ClaimService extends BaseService { for (const item of claim.additional_items) { const fulfillmentItem = successfullyFulfilled.find( - f => item.id === f.item_id + (f) => item.id === f.item_id ) if (fulfillmentItem) { @@ -485,7 +479,7 @@ class ClaimService extends BaseService { } async cancelFulfillment(fulfillmentId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const canceled = await this.fulfillmentService_ .withTransaction(manager) .cancelFulfillment(fulfillmentId) @@ -508,7 +502,7 @@ class ClaimService extends BaseService { } async processRefund(id) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claim = await this.retrieve(id, { relations: ["order", "order.payments"], }) @@ -560,7 +554,7 @@ class ClaimService extends BaseService { ) { const { metadata, no_notification } = config - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claim = await this.retrieve(id, { relations: ["additional_items"], }) @@ -584,7 +578,7 @@ class ClaimService extends BaseService { claim.fulfillment_status = "shipped" for (const i of claim.additional_items) { - const shipped = shipment.items.find(si => si.item_id === i.id) + const shipped = shipment.items.find((si) => si.item_id === i.id) if (shipped) { const shippedQty = (i.shipped_quantity || 0) + shipped.quantity await this.lineItemService_.withTransaction(manager).update(i.id, { @@ -617,7 +611,7 @@ class ClaimService extends BaseService { } async cancel(id) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const claim = await this.retrieve(id, { relations: ["return_order", "fulfillments", "order", "order.refunds"], }) @@ -665,6 +659,7 @@ class ClaimService extends BaseService { /** * @param {Object} selector - the query object for find + * @param {Object} config - the config object containing query settings * @return {Promise} the result of the find operation */ async list( @@ -678,7 +673,8 @@ class ClaimService extends BaseService { /** * Gets an order by id. - * @param {string} orderId - id of order to retrieve + * @param {string} claimId - id of order to retrieve + * @param {Object} config - the config object containing query settings * @return {Promise} the order document */ async retrieve(claimId, config = {}) { @@ -717,7 +713,7 @@ class ClaimService extends BaseService { const keyPath = `metadata.${key}` return this.orderModel_ .updateOne({ _id: validatedId }, { $unset: { [keyPath]: "" } }) - .catch(err => { + .catch((err) => { throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) }) } diff --git a/packages/medusa/src/services/discount.js b/packages/medusa/src/services/discount.js index 70f404f378..bb796208ce 100644 --- a/packages/medusa/src/services/discount.js +++ b/packages/medusa/src/services/discount.js @@ -1,14 +1,11 @@ -import _ from "lodash" -import randomize from "randomatic" import { BaseService } from "medusa-interfaces" import { Validator, MedusaError } from "medusa-core-utils" -import { MedusaErrorCodes } from "medusa-core-utils/dist/errors" import { parse, toSeconds } from "iso8601-duration" import { Brackets, ILike } from "typeorm" /** * Provides layer to manipulate discounts. - * @implements BaseService + * @implements {BaseService} */ class DiscountService extends BaseService { constructor({ @@ -17,7 +14,6 @@ class DiscountService extends BaseService { discountRuleRepository, giftCardRepository, totalsService, - productVariantService, productService, regionService, eventBusService, @@ -80,21 +76,13 @@ class DiscountService extends BaseService { id: Validator.string().optional(), description: Validator.string().optional(), type: Validator.string().required(), - value: Validator.number() - .min(0) - .required(), + value: Validator.number().min(0).required(), allocation: Validator.string().required(), valid_for: Validator.array().optional(), created_at: Validator.date().optional(), - updated_at: Validator.date() - .allow(null) - .optional(), - deleted_at: Validator.date() - .allow(null) - .optional(), - metadata: Validator.object() - .allow(null) - .optional(), + updated_at: Validator.date().allow(null).optional(), + deleted_at: Validator.date().allow(null).optional(), + metadata: Validator.object().allow(null).optional(), }) const { value, error } = schema.validate(discountRule) @@ -117,6 +105,7 @@ class DiscountService extends BaseService { /** * @param {Object} selector - the query object for find + * @param {Object} config - the config object containing query settings * @return {Promise} the result of the find operation */ async list(selector = {}, config = { relations: [], skip: 0, take: 10 }) { @@ -130,6 +119,7 @@ class DiscountService extends BaseService { /** * @param {Object} selector - the query object for find + * @param {Object} config - the config object containing query settings * @return {Promise} the result of the find operation */ async listAndCount( @@ -153,11 +143,11 @@ class DiscountService extends BaseService { delete where.code - query.where = qb => { + query.where = (qb) => { qb.where(where) qb.andWhere( - new Brackets(qb => { + new Brackets((qb) => { qb.where({ code: ILike(`%${q}%`) }) }) ) @@ -176,19 +166,19 @@ class DiscountService extends BaseService { * @return {Promise} the result of the create operation */ async create(discount) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const ruleRepo = manager.getCustomRepository(this.discountRuleRepository_) if (discount.rule?.valid_for) { - discount.rule.valid_for = discount.rule.valid_for.map(id => ({ id })) + discount.rule.valid_for = discount.rule.valid_for.map((id) => ({ id })) } const validatedRule = this.validateDiscountRule_(discount.rule) if (discount.regions) { discount.regions = await Promise.all( - discount.regions.map(regionId => + discount.regions.map((regionId) => this.regionService_.withTransaction(manager).retrieve(regionId) ) ) @@ -209,6 +199,7 @@ class DiscountService extends BaseService { /** * Gets a discount by id. * @param {string} discountId - id of discount to retrieve + * @param {Object} config - the config object containing query settings * @return {Promise} the discount */ async retrieve(discountId, config = {}) { @@ -233,6 +224,7 @@ class DiscountService extends BaseService { /** * Gets a discount by discount code. * @param {string} discountCode - discount code of discount to retrieve + * @param {array} relations - list of relations * @return {Promise} the discount document */ async retrieveByCode(discountCode, relations = []) { @@ -269,7 +261,7 @@ class DiscountService extends BaseService { * @return {Promise} the result of the update operation */ async update(discountId, update) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await this.retrieve(discountId) @@ -287,7 +279,7 @@ class DiscountService extends BaseService { if (regions) { discount.regions = await Promise.all( - regions.map(regionId => this.regionService_.retrieve(regionId)) + regions.map((regionId) => this.regionService_.retrieve(regionId)) ) } @@ -298,7 +290,9 @@ class DiscountService extends BaseService { if (rule) { discount.rule = this.validateDiscountRule_(rule) if (rule.valid_for) { - discount.rule.valid_for = discount.rule.valid_for.map(id => ({ id })) + discount.rule.valid_for = discount.rule.valid_for.map((id) => ({ + id, + })) } } @@ -314,11 +308,11 @@ class DiscountService extends BaseService { /** * Creates a dynamic code for a discount id. * @param {string} discountId - the id of the discount to create a code for - * @param {string} code - the code to identify the discount by + * @param {Object} data - the object containing a code to identify the discount by * @return {Promise} the newly created dynamic code */ async createDynamicCode(discountId, data) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await this.retrieve(discountId) @@ -367,13 +361,15 @@ class DiscountService extends BaseService { * @return {Promise} the newly created dynamic code */ async deleteDynamicCode(discountId, code) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await discountRepo.findOne({ where: { parent_discount_id: discountId, code }, }) - if (!discount) return Promise.resolve() + if (!discount) { + return Promise.resolve() + } await discountRepo.softRemove(discount) @@ -388,7 +384,7 @@ class DiscountService extends BaseService { * @return {Promise} the result of the update operation */ async addValidProduct(discountId, productId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRuleRepo = manager.getCustomRepository( this.discountRuleRepository_ ) @@ -399,7 +395,7 @@ class DiscountService extends BaseService { const { rule } = discount - const exists = rule.valid_for.find(p => p.id === productId) + const exists = rule.valid_for.find((p) => p.id === productId) // If product is already present, we return early if (exists) { return rule @@ -421,7 +417,7 @@ class DiscountService extends BaseService { * @return {Promise} the result of the update operation */ async removeValidProduct(discountId, productId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRuleRepo = manager.getCustomRepository( this.discountRuleRepository_ ) @@ -432,13 +428,13 @@ class DiscountService extends BaseService { const { rule } = discount - const exists = rule.valid_for.find(p => p.id === productId) + const exists = rule.valid_for.find((p) => p.id === productId) // If product is not present, we return early if (!exists) { return rule } - rule.valid_for = rule.valid_for.filter(p => p.id !== productId) + rule.valid_for = rule.valid_for.filter((p) => p.id !== productId) const updated = await discountRuleRepo.save(rule) return updated @@ -452,14 +448,14 @@ class DiscountService extends BaseService { * @return {Promise} the result of the update operation */ async addRegion(discountId, regionId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await this.retrieve(discountId, { relations: ["regions"], }) - const exists = discount.regions.find(r => r.id === regionId) + const exists = discount.regions.find((r) => r.id === regionId) // If region is already present, we return early if (exists) { return discount @@ -481,20 +477,20 @@ class DiscountService extends BaseService { * @return {Promise} the result of the update operation */ async removeRegion(discountId, regionId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await this.retrieve(discountId, { relations: ["regions"], }) - const exists = discount.regions.find(r => r.id === regionId) + const exists = discount.regions.find((r) => r.id === regionId) // If region is not present, we return early if (!exists) { return discount } - discount.regions = discount.regions.filter(r => r.id !== regionId) + discount.regions = discount.regions.filter((r) => r.id !== regionId) const updated = await discountRepo.save(discount) return updated @@ -507,12 +503,14 @@ class DiscountService extends BaseService { * @return {Promise} the result of the delete operation */ async delete(discountId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const discountRepo = manager.getCustomRepository(this.discountRepository_) const discount = await discountRepo.findOne({ where: { id: discountId } }) - if (!discount) return Promise.resolve() + if (!discount) { + return Promise.resolve() + } await discountRepo.softRemove(discount) @@ -522,7 +520,7 @@ class DiscountService extends BaseService { /** * Decorates a discount. - * @param {Discount} discount - the discount to decorate. + * @param {string} discountId - id of discount to decorate * @param {string[]} fields - the fields to include. * @param {string[]} expandFields - fields to expand. * @return {Discount} return the decorated discount. diff --git a/packages/medusa/src/services/fulfillment.js b/packages/medusa/src/services/fulfillment.js index ed0b4e4f80..b2cd6b71bc 100644 --- a/packages/medusa/src/services/fulfillment.js +++ b/packages/medusa/src/services/fulfillment.js @@ -1,10 +1,9 @@ -import _ from "lodash" import { BaseService } from "medusa-interfaces" import { MedusaError } from "medusa-core-utils" /** * Handles Fulfillments - * @implements BaseService + * @extends BaseService */ class FulfillmentService extends BaseService { constructor({ @@ -61,7 +60,7 @@ class FulfillmentService extends BaseService { } partitionItems_(shippingMethods, items) { - let partitioned = [] + const partitioned = [] // partition order items to their dedicated shipping method for (const method of shippingMethods) { const temp = { shipping_method: method } @@ -95,12 +94,12 @@ class FulfillmentService extends BaseService { async getFulfillmentItems_(order, items, transformer) { const toReturn = await Promise.all( items.map(async ({ item_id, quantity }) => { - const item = order.items.find(i => i.id === item_id) + const item = order.items.find((i) => i.id === item_id) return transformer(item, quantity) }) ) - return toReturn.filter(i => !!i) + return toReturn.filter((i) => !!i) } /** @@ -137,6 +136,7 @@ class FulfillmentService extends BaseService { /** * Retrieves a fulfillment by its id. * @param {string} id - the id of the fulfillment to retrieve + * @param {object} config - optional values to include with fulfillmentRepository query * @return {Fulfillment} the fulfillment */ async retrieve(id, config = {}) { @@ -165,11 +165,11 @@ class FulfillmentService extends BaseService { * those partitions. * @param {Order} order - order to create fulfillment for * @param {{ item_id: string, quantity: number}[]} itemsToFulfill - the items in the order to fulfill - * @param {object} metadata - potential metadata to add + * @param {object} custom - potential custom values to add * @return {Fulfillment[]} the created fulfillments */ async createFulfillment(order, itemsToFulfill, custom = {}) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const fulfillmentRepository = manager.getCustomRepository( this.fulfillmentRepository_ ) @@ -190,18 +190,19 @@ class FulfillmentService extends BaseService { const ful = fulfillmentRepository.create({ ...custom, provider_id: shipping_method.shipping_option.provider_id, - items: items.map(i => ({ item_id: i.id, quantity: i.quantity })), + items: items.map((i) => ({ item_id: i.id, quantity: i.quantity })), data: {}, }) - let result = await fulfillmentRepository.save(ful) + const result = await fulfillmentRepository.save(ful) - result.data = await this.fulfillmentProviderService_.createFulfillment( - shipping_method, - items, - { ...order }, - { ...result } - ) + result.data = + await this.fulfillmentProviderService_.createFulfillment( + shipping_method, + items, + { ...order }, + { ...result } + ) return fulfillmentRepository.save(result) }) @@ -220,7 +221,7 @@ class FulfillmentService extends BaseService { * */ cancelFulfillment(fulfillmentOrId) { - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { let id = fulfillmentOrId if (typeof fulfillmentOrId === "object") { id = fulfillmentOrId.id @@ -260,9 +261,9 @@ class FulfillmentService extends BaseService { /** * Creates a shipment by marking a fulfillment as shipped. Adds - * tracking numbers and potentially more metadata. + * tracking links and potentially more metadata. * @param {Order} fulfillmentId - the fulfillment to ship - * @param {TrackingLink[]} trackingNumbers - tracking numbers for the shipment + * @param {TrackingLink[]} trackingLinks - tracking links for the shipment * @param {object} config - potential configuration settings, such as no_notification and metadata * @return {Fulfillment} the shipped fulfillment */ @@ -276,7 +277,7 @@ class FulfillmentService extends BaseService { ) { const { metadata, no_notification } = config - return this.atomicPhase_(async manager => { + return this.atomicPhase_(async (manager) => { const fulfillmentRepository = manager.getCustomRepository( this.fulfillmentRepository_ ) @@ -298,7 +299,7 @@ class FulfillmentService extends BaseService { const now = new Date() fulfillment.shipped_at = now - fulfillment.tracking_links = trackingLinks.map(tl => + fulfillment.tracking_links = trackingLinks.map((tl) => trackingLinkRepo.create(tl) )