diff --git a/.changeset/polite-llamas-sit.md b/.changeset/polite-llamas-sit.md new file mode 100644 index 0000000000..93c7e283c5 --- /dev/null +++ b/.changeset/polite-llamas-sit.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): Rounding issues on line item adjustments diff --git a/integration-tests/api/__tests__/admin/draft-order/draft-order.js b/integration-tests/api/__tests__/admin/draft-order/draft-order.js index 4e290d7cb9..18cf678659 100644 --- a/integration-tests/api/__tests__/admin/draft-order/draft-order.js +++ b/integration-tests/api/__tests__/admin/draft-order/draft-order.js @@ -572,11 +572,10 @@ describe("/admin/draft-orders", () => { (item) => item.variant_id === testVariant2Id ) - const lineItem1WeightInTotal = 0.444 // line item amount / amount - const lineItem2WeightInTotal = 0.556 // line item amount / amount - expect(draftOrder.cart.items).toHaveLength(2) + expect(lineItem1.adjustments).toHaveLength(1) + expect(lineItem1.adjustments[0].amount).toBeCloseTo(444, 0) // discountAmount * (line item amount / amount) = 444.4444444444 expect(lineItem1).toEqual( expect.objectContaining({ variant_id: testVariantId, @@ -585,7 +584,6 @@ describe("/admin/draft-orders", () => { adjustments: expect.arrayContaining([ expect.objectContaining({ item_id: lineItem1.id, - amount: discountAmount * lineItem1WeightInTotal, description: "discount", discount_id: discount.id, }), @@ -593,6 +591,8 @@ describe("/admin/draft-orders", () => { }) ) + expect(lineItem2.adjustments).toHaveLength(1) + expect(lineItem2.adjustments[0].amount).toBeCloseTo(556, 0) // discountAmount * (line item amount / amount) = 555.5555555555 expect(lineItem2).toEqual( expect.objectContaining({ variant_id: testVariant2Id, @@ -601,7 +601,6 @@ describe("/admin/draft-orders", () => { adjustments: expect.arrayContaining([ expect.objectContaining({ item_id: lineItem2.id, - amount: discountAmount * lineItem2WeightInTotal, description: "discount", discount_id: discount.id, }), diff --git a/integration-tests/api/__tests__/admin/order-edit/order-edit.js b/integration-tests/api/__tests__/admin/order-edit/order-edit.js index c8c3a2c1d1..c2d52c3605 100644 --- a/integration-tests/api/__tests__/admin/order-edit/order-edit.js +++ b/integration-tests/api/__tests__/admin/order-edit/order-edit.js @@ -2482,6 +2482,9 @@ describe("/admin/order-edits", () => { ) expect(item2.adjustments).toHaveLength(1) + expect(item1.adjustments[0].amount).toBeCloseTo(1333, 0) + expect(item2.adjustments[0].amount).toBeCloseTo(667, 0) + expect(response.data.order_edit).toEqual( expect.objectContaining({ id: orderEditId, @@ -2531,7 +2534,6 @@ describe("/admin/order-edits", () => { adjustments: expect.arrayContaining([ expect.objectContaining({ discount_id: discount.id, - amount: 1333, }), ]), }), @@ -2564,7 +2566,6 @@ describe("/admin/order-edits", () => { adjustments: expect.arrayContaining([ expect.objectContaining({ discount_id: discount.id, - amount: 667, }), ]), }), diff --git a/integration-tests/api/__tests__/store/cart/cart.js b/integration-tests/api/__tests__/store/cart/cart.js index 233abf535b..ee72f0272f 100644 --- a/integration-tests/api/__tests__/store/cart/cart.js +++ b/integration-tests/api/__tests__/store/cart/cart.js @@ -604,13 +604,22 @@ describe("/store/carts", () => { .catch((err) => console.log(err)) expect(response.data.cart.items.length).toEqual(2) + + const item1 = response.data.cart.items.find((i) => i.id === "test-li") + expect(item1.adjustments).toHaveLength(1) + + const item2 = response.data.cart.items.find((i) => i.id !== "test-li") + expect(item2.adjustments).toHaveLength(1) + + expect(item1.adjustments[0].amount).toBeCloseTo(17, 0) + expect(item2.adjustments[0].amount).toBeCloseTo(168, 0) + expect(response.data.cart.items).toEqual( expect.arrayContaining([ expect.objectContaining({ adjustments: [ expect.objectContaining({ item_id: "test-li", - amount: 17, discount_id: "medusa-185", }), ], @@ -618,7 +627,6 @@ describe("/store/carts", () => { expect.objectContaining({ adjustments: [ expect.objectContaining({ - amount: 168, discount_id: "medusa-185", }), ], @@ -663,14 +671,23 @@ describe("/store/carts", () => { .catch((err) => console.log(err)) expect(response.data.cart.items.length).toEqual(2) + + const item1 = response.data.cart.items.find((i) => i.id === "test-li") + expect(item1.adjustments).toHaveLength(1) + + const item2 = response.data.cart.items.find( + (i) => i.id === "line-item-2" + ) + expect(item2.adjustments).toHaveLength(1) + expect(response.data.cart.items).toEqual( expect.arrayContaining([ expect.objectContaining({ adjustments: [ expect.objectContaining({ item_id: "test-li", + amount: 9.25, discount_id: "medusa-185", - amount: 9, }), ], }), @@ -678,7 +695,7 @@ describe("/store/carts", () => { adjustments: [ expect.objectContaining({ item_id: "line-item-2", - amount: 176, + amount: 175.75, discount_id: "medusa-185", }), ], diff --git a/integration-tests/api/__tests__/store/orders.js b/integration-tests/api/__tests__/store/orders.js index 686d6ab657..620ead7bd5 100644 --- a/integration-tests/api/__tests__/store/orders.js +++ b/integration-tests/api/__tests__/store/orders.js @@ -166,6 +166,7 @@ describe("/store/carts", () => { // fields "status", "email", + // relations "shipping_address", "fulfillments", @@ -175,6 +176,18 @@ describe("/store/carts", () => { "customer", "payments", "region", + + // totals + "shipping_total", + "discount_total", + "tax_total", + "refunded_total", + "total", + "subtotal", + "paid_total", + "refundable_amount", + "gift_card_total", + "gift_card_tax_total", ]) }) @@ -186,6 +199,7 @@ describe("/store/carts", () => { expect(Object.keys(response.data.order)).toEqual([ // fields "status", + // default relations "shipping_address", "fulfillments", @@ -195,6 +209,18 @@ describe("/store/carts", () => { "customer", "payments", "region", + + // totals + "shipping_total", + "discount_total", + "tax_total", + "refunded_total", + "total", + "subtotal", + "paid_total", + "refundable_amount", + "gift_card_total", + "gift_card_tax_total", ]) }) @@ -208,8 +234,21 @@ describe("/store/carts", () => { expect(Object.keys(response.data.order)).toEqual([ // fields "status", + // selected relations "billing_address", + + // totals + "shipping_total", + "discount_total", + "tax_total", + "refunded_total", + "total", + "subtotal", + "paid_total", + "refundable_amount", + "gift_card_total", + "gift_card_tax_total", ]) }) diff --git a/integration-tests/plugins/__tests__/medusa-plugin-sendgrid/__snapshots__/index.js.snap b/integration-tests/plugins/__tests__/medusa-plugin-sendgrid/__snapshots__/index.js.snap index e9235797db..91184002f5 100644 --- a/integration-tests/plugins/__tests__/medusa-plugin-sendgrid/__snapshots__/index.js.snap +++ b/integration-tests/plugins/__tests__/medusa-plugin-sendgrid/__snapshots__/index.js.snap @@ -340,6 +340,7 @@ Object { "original_tax_total": 200, "original_total": 1200, "quantity": 1, + "raw_discount_total": 0, "subtotal": 1000, "tax_lines": Array [ Object { @@ -454,6 +455,7 @@ Object { "original_tax_total": 400, "original_total": 2400, "quantity": 2, + "raw_discount_total": 0, "returned_quantity": 1, "shipped_quantity": 2, "should_merge": true, @@ -804,6 +806,7 @@ Object { "original_total": 2400, "price": "10.00 USD", "quantity": 2, + "raw_discount_total": 0, "returned_quantity": null, "shipped_quantity": null, "should_merge": true, @@ -1037,6 +1040,7 @@ Object { "original_total": 2400, "price": "12.00 USD", "quantity": 2, + "raw_discount_total": 0, "returned_quantity": null, "shipped_quantity": 2, "should_merge": true, @@ -1063,6 +1067,7 @@ Object { "original_tax_total": 400, "original_total": 2400, "quantity": 2, + "raw_discount_total": 0, "subtotal": 2000, "tax_lines": Array [ Object { @@ -1313,6 +1318,7 @@ Object { "original_tax_total": 400, "original_total": 2400, "quantity": 2, + "raw_discount_total": 0, "returned_quantity": null, "shipped_quantity": 2, "should_merge": true, @@ -1531,6 +1537,7 @@ Object { "original_tax_total": 200, "original_total": 1200, "quantity": 1, + "raw_discount_total": 0, "subtotal": 1000, "tax_lines": Array [ Object { @@ -1645,6 +1652,7 @@ Object { "original_tax_total": 400, "original_total": 2400, "quantity": 2, + "raw_discount_total": 0, "returned_quantity": null, "shipped_quantity": 2, "should_merge": true, diff --git a/packages/medusa/src/api/middlewares/index.ts b/packages/medusa/src/api/middlewares/index.ts index 68aa757c54..654ae3e8b4 100644 --- a/packages/medusa/src/api/middlewares/index.ts +++ b/packages/medusa/src/api/middlewares/index.ts @@ -9,7 +9,7 @@ export { getRequestedBatchJob } from "./batch-job/get-requested-batch-job" export { doesConditionBelongToDiscount } from "./discount/does-condition-belong-to-discount" export { transformIncludesOptions } from "./transform-includes-options" export { transformBody } from "./transform-body" -export { transformQuery } from "./transform-query" +export { transformQuery, transformStoreQuery } from "./transform-query" export default { authenticate, diff --git a/packages/medusa/src/api/middlewares/transform-query.ts b/packages/medusa/src/api/middlewares/transform-query.ts index 6d3f93c9fe..b074368cf0 100644 --- a/packages/medusa/src/api/middlewares/transform-query.ts +++ b/packages/medusa/src/api/middlewares/transform-query.ts @@ -12,9 +12,56 @@ import { FindConfig, QueryConfig, RequestQueryFields } from "../../types/common" import { omit } from "lodash" import { removeUndefinedProperties } from "../../utils" +/** + * Middleware that transform the query input for the admin end points + * @param plainToClass + * @param queryConfig + * @param config + */ export function transformQuery< T extends RequestQueryFields, TEntity extends BaseEntity +>( + plainToClass: ClassConstructor, + queryConfig?: Omit< + QueryConfig, + "allowedRelations" | "allowedFields" + >, + config: ValidatorOptions = {} +): (req: Request, res: Response, next: NextFunction) => Promise { + return async (req: Request, res: Response, next: NextFunction) => { + try { + normalizeQuery()(req, res, () => void 0) + const validated: T = await validator>( + plainToClass, + req.query, + config + ) + req.validatedQuery = validated + req.filterableFields = getFilterableFields(validated) + req.allowedProperties = getAllowedProperties( + validated, + req.includes ?? {}, + queryConfig + ) + attachListOrRetrieveConfig(req, queryConfig) + + next() + } catch (e) { + next(e) + } + } +} + +/** + * Middleware that transform the query input for the store endpoints + * @param plainToClass + * @param queryConfig + * @param config + */ +export function transformStoreQuery< + T extends RequestQueryFields, + TEntity extends BaseEntity >( plainToClass: ClassConstructor, queryConfig?: QueryConfig, @@ -29,47 +76,13 @@ export function transformQuery< config ) req.validatedQuery = validated - - req.filterableFields = omit(validated, [ - "limit", - "offset", - "expand", - "fields", - "order", - ]) - req.filterableFields = removeUndefinedProperties(req.filterableFields) - - if ( - (queryConfig?.defaultFields || validated.fields) && - (queryConfig?.defaultRelations || validated.expand) - ) { - req.allowedProperties = [ - ...(validated.fields - ? validated.fields.split(",") - : queryConfig?.allowedFields || [])!, - ...(validated.expand - ? validated.expand.split(",") - : queryConfig?.allowedRelations || [])!, - ] as unknown as string[] - } - - const includesFields = Object.keys(req["includes"] ?? {}) - if (includesFields.length) { - req.allowedProperties = req.allowedProperties ?? [] - req.allowedProperties.push(...includesFields) - } - - if (queryConfig?.isList) { - req.listConfig = prepareListQuery( - validated, - queryConfig - ) as FindConfig - } else { - req.retrieveConfig = prepareRetrieveQuery( - validated, - queryConfig - ) as FindConfig - } + req.filterableFields = getFilterableFields(validated) + req.allowedProperties = getStoreAllowedProperties( + validated, + req.includes ?? {}, + queryConfig + ) + attachListOrRetrieveConfig(req, queryConfig) next() } catch (e) { @@ -77,3 +90,97 @@ export function transformQuery< } } } + +/** + * Omit the non filterable config from the validated object + * @param obj + */ +function getFilterableFields(obj: T): T { + const result = omit(obj, [ + "limit", + "offset", + "expand", + "fields", + "order", + ]) as T + return removeUndefinedProperties(result) +} + +/** + * build and attach the `retrieveConfig` or `listConfig` + * @param req + * @param queryConfig + */ +function attachListOrRetrieveConfig( + req: Request, + queryConfig?: QueryConfig +) { + const validated = req.validatedQuery + if (queryConfig?.isList) { + req.listConfig = prepareListQuery( + validated, + queryConfig + ) as FindConfig + } else { + req.retrieveConfig = prepareRetrieveQuery( + validated, + queryConfig + ) as FindConfig + } +} +/** + * Build the store allowed props based on the custom fields query params, the allowed props config and the includes options. + * This can be used later with `cleanResponseData` in order to clean up the returned objects to the client. + * @param queryConfig + * @param validated + * @param includesOptions + */ +function getStoreAllowedProperties( + validated: RequestQueryFields, + includesOptions: Record, + queryConfig?: QueryConfig +): string[] { + const allowed: string[] = [] + + const includeKeys = Object.keys(includesOptions) + const fields = validated.fields + ? validated.fields?.split(",") + : queryConfig?.allowedFields || [] + const expand = + validated.expand || includeKeys.length + ? [...(validated.expand?.split(",") || []), ...includeKeys] + : queryConfig?.allowedRelations || [] + + allowed.push(...fields, ...expand) + + return allowed +} + +/** + * Build the admin allowed props based on the custom fields query params, the defaults and the includes options. + * Since admin can access everything, it is only in order to return what the user asked for through fields and expand query params. + * This can be used later with `cleanResponseData` in order to clean up the returned objects to the client. + * @param queryConfig + * @param validated + * @param includesOptions + */ +function getAllowedProperties( + validated: RequestQueryFields, + includesOptions: Record, + queryConfig?: QueryConfig +): string[] { + const allowed: (string | keyof TEntity)[] = [] + + const includeKeys = Object.keys(includesOptions) + const fields = validated.fields + ? validated.fields?.split(",") + : queryConfig?.defaultFields || [] + const expand = + validated.expand || includeKeys.length + ? [...(validated.expand?.split(",") || []), ...includeKeys] + : queryConfig?.defaultRelations || [] + + allowed.push(...fields, ...expand) + + return allowed as string[] +} diff --git a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.ts b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.ts index 8e65df24e3..1cc7913dd5 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.ts @@ -25,6 +25,7 @@ import { AddressPayload } from "../../../../types/common" import { DraftOrderCreateProps } from "../../../../types/draft-orders" import { validator } from "../../../../utils/validator" import { IsType } from "../../../../utils/validators/is-type" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /draft-orders @@ -154,7 +155,7 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.status(200).json({ draft_order: draftOrder }) + res.status(200).json({ draft_order: cleanResponseData(draftOrder, []) }) } enum Status { diff --git a/packages/medusa/src/api/routes/admin/draft-orders/create-line-item.ts b/packages/medusa/src/api/routes/admin/draft-orders/create-line-item.ts index 18497b0911..9dc336888c 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/create-line-item.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/create-line-item.ts @@ -13,6 +13,7 @@ import { import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { validator } from "../../../../utils/validator" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /draft-orders/{id}/line-items @@ -138,7 +139,9 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.status(200).json({ draft_order: draftOrder }) + res.status(200).json({ + draft_order: cleanResponseData(draftOrder, []), + }) }) } diff --git a/packages/medusa/src/api/routes/admin/draft-orders/delete-line-item.ts b/packages/medusa/src/api/routes/admin/draft-orders/delete-line-item.ts index 4395817cbc..39e0ce95bf 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/delete-line-item.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/delete-line-item.ts @@ -8,6 +8,7 @@ import { import { DraftOrder } from "../../../.." import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [delete] /draft-orders/{id}/line-items/{line_id} @@ -93,6 +94,8 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.status(200).json({ draft_order: draftOrder }) + res.status(200).json({ + draft_order: cleanResponseData(draftOrder, []), + }) }) } diff --git a/packages/medusa/src/api/routes/admin/draft-orders/get-draft-order.ts b/packages/medusa/src/api/routes/admin/draft-orders/get-draft-order.ts index c3c87382ba..2928a88714 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/get-draft-order.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/get-draft-order.ts @@ -7,6 +7,7 @@ import { } from "." import { DraftOrder } from "../../../.." +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [get] /draft-orders/{id} @@ -77,5 +78,7 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.json({ draft_order: draftOrder }) + res.json({ + draft_order: cleanResponseData(draftOrder, []), + }) } diff --git a/packages/medusa/src/api/routes/admin/draft-orders/register-payment.ts b/packages/medusa/src/api/routes/admin/draft-orders/register-payment.ts index c3632fdb59..b7eea18a0a 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/register-payment.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/register-payment.ts @@ -13,6 +13,7 @@ import { import { EntityManager } from "typeorm" import { Order } from "../../../../models" import { MedusaError } from "medusa-core-utils" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /draft-orders/{id}/pay @@ -122,7 +123,7 @@ export default async (req, res) => { return order }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } export const reserveQuantityForDraftOrder = async ( diff --git a/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.ts b/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.ts index 78abe0ab09..d4dae007f9 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.ts @@ -19,6 +19,7 @@ import { CartUpdateProps } from "../../../../types/cart" import { AddressPayload } from "../../../../types/common" import { validator } from "../../../../utils/validator" import { IsType } from "../../../../utils/validators/is-type" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /admin/draft-orders/{id} @@ -137,7 +138,7 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.status(200).json({ draft_order: draftOrder }) + res.status(200).json({ draft_order: cleanResponseData(draftOrder, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/draft-orders/update-line-item.ts b/packages/medusa/src/api/routes/admin/draft-orders/update-line-item.ts index c38ba03aec..a57c533d02 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/update-line-item.ts +++ b/packages/medusa/src/api/routes/admin/draft-orders/update-line-item.ts @@ -11,6 +11,7 @@ import { EntityManager } from "typeorm" import { LineItemUpdate } from "../../../../types/cart" import { MedusaError } from "medusa-core-utils" import { validator } from "../../../../utils/validator" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /draft-orders/{id}/line-items/{line_id} @@ -139,7 +140,9 @@ export default async (req, res) => { select: defaultAdminDraftOrdersCartFields, }) - res.status(200).json({ draft_order: draftOrder }) + res.status(200).json({ + draft_order: cleanResponseData(draftOrder, []), + }) }) } diff --git a/packages/medusa/src/api/routes/admin/orders/add-shipping-method.ts b/packages/medusa/src/api/routes/admin/orders/add-shipping-method.ts index e5664f7de5..71e330b2ac 100644 --- a/packages/medusa/src/api/routes/admin/orders/add-shipping-method.ts +++ b/packages/medusa/src/api/routes/admin/orders/add-shipping-method.ts @@ -9,6 +9,7 @@ import { import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/shipping-methods @@ -97,7 +98,7 @@ export default async (req, res) => { includes: req.includes, }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/archive-order.ts b/packages/medusa/src/api/routes/admin/orders/archive-order.ts index e6c39fbd30..3da5517688 100644 --- a/packages/medusa/src/api/routes/admin/orders/archive-order.ts +++ b/packages/medusa/src/api/routes/admin/orders/archive-order.ts @@ -1,6 +1,7 @@ import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/archive @@ -70,7 +71,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersOrderArchiveParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-claim.ts b/packages/medusa/src/api/routes/admin/orders/cancel-claim.ts index 6e5b1797b2..81ae1ffaa2 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-claim.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-claim.ts @@ -3,6 +3,7 @@ import { ClaimService, OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/claims/{claim_id}/cancel @@ -85,7 +86,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersClaimCancel extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-claim.ts b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-claim.ts index d16af0b62d..e6461868bd 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-claim.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-claim.ts @@ -7,6 +7,7 @@ import { import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/claims/{claim_id}/fulfillments/{fulfillment_id}/cancel @@ -101,7 +102,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersClaimFulfillmentsCancelParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-swap.ts b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-swap.ts index 82d4464017..421d3d8873 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-swap.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment-swap.ts @@ -7,6 +7,7 @@ import { import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/swaps/{swap_id}/fulfillments/{fulfillment_id}/cancel @@ -101,7 +102,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } // eslint-disable-next-line max-len diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment.ts b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment.ts index 464872e1b1..74ae8c8531 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-fulfillment.ts @@ -9,6 +9,7 @@ import { MedusaError } from "medusa-core-utils" import { Fulfillment } from "../../../../models" import { IInventoryService } from "../../../../interfaces" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/fulfillments/{fulfillment_id}/cancel @@ -108,7 +109,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export const adjustInventoryForCancelledFulfillment = async ( diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-order.ts b/packages/medusa/src/api/routes/admin/orders/cancel-order.ts index d9a9070d5a..d475a8aecf 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-order.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-order.ts @@ -1,6 +1,7 @@ import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/cancel @@ -69,7 +70,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersOrderCancel extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/cancel-swap.ts b/packages/medusa/src/api/routes/admin/orders/cancel-swap.ts index 9d04d0da7e..76e5aa9990 100644 --- a/packages/medusa/src/api/routes/admin/orders/cancel-swap.ts +++ b/packages/medusa/src/api/routes/admin/orders/cancel-swap.ts @@ -3,6 +3,7 @@ import { OrderService, SwapService } from "../../../../services" import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/swaps/{swap_id}/cancel @@ -83,7 +84,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersSwapCancelParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/capture-payment.ts b/packages/medusa/src/api/routes/admin/orders/capture-payment.ts index 9cbfe80c75..332804d377 100644 --- a/packages/medusa/src/api/routes/admin/orders/capture-payment.ts +++ b/packages/medusa/src/api/routes/admin/orders/capture-payment.ts @@ -1,6 +1,7 @@ import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/capture @@ -72,7 +73,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersOrderCaptureParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/complete-order.ts b/packages/medusa/src/api/routes/admin/orders/complete-order.ts index e3b69958ba..e0baeb5013 100644 --- a/packages/medusa/src/api/routes/admin/orders/complete-order.ts +++ b/packages/medusa/src/api/routes/admin/orders/complete-order.ts @@ -1,6 +1,7 @@ import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/complete @@ -72,7 +73,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminPostOrdersOrderCompleteParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/create-claim-shipment.ts b/packages/medusa/src/api/routes/admin/orders/create-claim-shipment.ts index 025e640e01..9613957d32 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-claim-shipment.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-claim-shipment.ts @@ -2,6 +2,7 @@ import { ClaimService, OrderService } from "../../../../services" import { IsArray, IsNotEmpty, IsOptional, IsString } from "class-validator" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/claims/{claim_id}/shipments @@ -92,7 +93,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/create-claim.ts b/packages/medusa/src/api/routes/admin/orders/create-claim.ts index 0f24d9d68a..cc3c40120b 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-claim.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-claim.ts @@ -16,6 +16,7 @@ import { MedusaError } from "medusa-core-utils" import { EntityManager } from "typeorm" import { ClaimTypeValue } from "../../../../types/claim" import { AddressPayload, FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /order/{id}/claims @@ -254,7 +255,9 @@ export default async (req, res) => { return { response_code: 200, - response_body: { order }, + response_body: { + order, + }, } }) }) @@ -288,6 +291,13 @@ export default async (req, res) => { throw err } + if (idempotencyKey.response_body.order) { + idempotencyKey.response_body.order = cleanResponseData( + idempotencyKey.response_body.order, + [] + ) + } + res.status(idempotencyKey.response_code).json(idempotencyKey.response_body) } diff --git a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts index 7484e565c7..2012f9f2dd 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.ts @@ -18,6 +18,7 @@ import { import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean" import { Fulfillment, LineItem } from "../../../../models" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/fulfillment @@ -139,7 +140,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } const updateInventoryAndReservations = async ( diff --git a/packages/medusa/src/api/routes/admin/orders/create-shipment.ts b/packages/medusa/src/api/routes/admin/orders/create-shipment.ts index a3984fdfc7..806ac9c1f6 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-shipment.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-shipment.ts @@ -10,6 +10,7 @@ import { EntityManager } from "typeorm" import { OrderService } from "../../../../services" import { TrackingLink } from "../../../../models" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/shipment @@ -104,7 +105,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.ts b/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.ts index c914d1236e..e193585248 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.ts @@ -10,6 +10,7 @@ import { OrderService, SwapService } from "../../../../services" import { EntityManager } from "typeorm" import { validator } from "../../../../utils/validator" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/swaps/{swap_id}/shipments @@ -102,7 +103,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/create-swap.ts b/packages/medusa/src/api/routes/admin/orders/create-swap.ts index 38c38ffdc7..0283e673c6 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-swap.ts +++ b/packages/medusa/src/api/routes/admin/orders/create-swap.ts @@ -21,6 +21,7 @@ import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils" import { Type } from "class-transformer" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /order/{id}/swaps @@ -216,7 +217,9 @@ export default async (req, res) => { return { response_code: 200, - response_body: { order }, + response_body: { + order: cleanResponseData(order, []), + }, } }) }) diff --git a/packages/medusa/src/api/routes/admin/orders/fulfill-claim.ts b/packages/medusa/src/api/routes/admin/orders/fulfill-claim.ts index ad7ef08093..45ef555ebd 100644 --- a/packages/medusa/src/api/routes/admin/orders/fulfill-claim.ts +++ b/packages/medusa/src/api/routes/admin/orders/fulfill-claim.ts @@ -3,6 +3,7 @@ import { IsBoolean, IsObject, IsOptional } from "class-validator" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/claims/{claim_id}/fulfillments @@ -84,7 +85,7 @@ export default async (req, res) => { includes: req.includes, }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/fulfill-swap.ts b/packages/medusa/src/api/routes/admin/orders/fulfill-swap.ts index 4edfc7a521..03c41f2e04 100644 --- a/packages/medusa/src/api/routes/admin/orders/fulfill-swap.ts +++ b/packages/medusa/src/api/routes/admin/orders/fulfill-swap.ts @@ -4,6 +4,7 @@ import { OrderService, SwapService } from "../../../../services" import { EntityManager } from "typeorm" import { validator } from "../../../../utils/validator" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/swaps/{swap_id}/fulfillments @@ -88,7 +89,7 @@ export default async (req, res) => { includes: req.includes, }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/get-order.ts b/packages/medusa/src/api/routes/admin/orders/get-order.ts index 1ae1a6c26c..8841ab4edc 100644 --- a/packages/medusa/src/api/routes/admin/orders/get-order.ts +++ b/packages/medusa/src/api/routes/admin/orders/get-order.ts @@ -1,5 +1,6 @@ import { OrderService } from "../../../../services" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [get] /orders/{id} @@ -64,7 +65,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order: order }) + res.json({ order: cleanResponseData(order, []) }) } export class AdminGetOrdersOrderParams extends FindParams {} diff --git a/packages/medusa/src/api/routes/admin/orders/index.ts b/packages/medusa/src/api/routes/admin/orders/index.ts index cce3b2288c..85c915c981 100644 --- a/packages/medusa/src/api/routes/admin/orders/index.ts +++ b/packages/medusa/src/api/routes/admin/orders/index.ts @@ -94,7 +94,7 @@ export default (app, featureFlagRouter: FlagRouter) => { transformIncludesOptions(allowedOrderIncludesFields), transformQuery(AdminGetOrdersParams, { defaultRelations: relations, - defaultFields: defaultAdminOrdersFields, + defaultFields: defaultFields, isList: true, }), middlewares.wrap(require("./list-orders").default) diff --git a/packages/medusa/src/api/routes/admin/orders/list-orders.ts b/packages/medusa/src/api/routes/admin/orders/list-orders.ts index 83bf18192e..6982a8c5dc 100644 --- a/packages/medusa/src/api/routes/admin/orders/list-orders.ts +++ b/packages/medusa/src/api/routes/admin/orders/list-orders.ts @@ -5,6 +5,7 @@ import { Order } from "../../../../models" import { OrderService } from "../../../../services" import { Type } from "class-transformer" import { pick } from "lodash" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [get] /orders @@ -214,7 +215,12 @@ export default async (req, res) => { data = orders.map((o) => pick(o, fields)) } - res.json({ orders: data, count, offset: skip, limit: take }) + res.json({ + orders: cleanResponseData(data, []), + count, + offset: skip, + limit: take, + }) } export class AdminGetOrdersParams extends AdminListOrdersSelector { diff --git a/packages/medusa/src/api/routes/admin/orders/process-swap-payment.ts b/packages/medusa/src/api/routes/admin/orders/process-swap-payment.ts index 1e1ec5481a..01f49e1d6c 100644 --- a/packages/medusa/src/api/routes/admin/orders/process-swap-payment.ts +++ b/packages/medusa/src/api/routes/admin/orders/process-swap-payment.ts @@ -2,6 +2,7 @@ import { OrderService, SwapService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/swaps/{swap_id}/process-payment @@ -73,7 +74,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } // eslint-disable-next-line max-len diff --git a/packages/medusa/src/api/routes/admin/orders/refund-payment.ts b/packages/medusa/src/api/routes/admin/orders/refund-payment.ts index a18a6316e8..b93023d48c 100644 --- a/packages/medusa/src/api/routes/admin/orders/refund-payment.ts +++ b/packages/medusa/src/api/routes/admin/orders/refund-payment.ts @@ -9,6 +9,7 @@ import { import { OrderService } from "../../../../services" import { EntityManager } from "typeorm" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/refund @@ -97,7 +98,7 @@ export default async (req, res) => { includes: req.includes, }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/request-return.ts b/packages/medusa/src/api/routes/admin/orders/request-return.ts index 35040c54a0..71ac895e9f 100644 --- a/packages/medusa/src/api/routes/admin/orders/request-return.ts +++ b/packages/medusa/src/api/routes/admin/orders/request-return.ts @@ -18,6 +18,7 @@ import { EntityManager } from "typeorm" import { Order, Return } from "../../../../models" import { OrdersReturnItem } from "../../../../types/orders" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id}/return @@ -237,7 +238,9 @@ export default async (req, res) => { return { response_code: 200, - response_body: { order }, + response_body: { + order: cleanResponseData(order, []), + }, } }) }) diff --git a/packages/medusa/src/api/routes/admin/orders/update-claim.ts b/packages/medusa/src/api/routes/admin/orders/update-claim.ts index e3f65aacdc..e894f688e9 100644 --- a/packages/medusa/src/api/routes/admin/orders/update-claim.ts +++ b/packages/medusa/src/api/routes/admin/orders/update-claim.ts @@ -14,6 +14,7 @@ import { Type } from "class-transformer" import { EntityManager } from "typeorm" import { validator } from "../../../../utils/validator" import { FindParams } from "../../../../types/common" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /order/{id}/claims/{claim_id} @@ -103,7 +104,7 @@ export default async (req, res) => { includes: req.includes, }) - res.json({ order: data }) + res.json({ order: cleanResponseData(data, []) }) } /** diff --git a/packages/medusa/src/api/routes/admin/orders/update-order.ts b/packages/medusa/src/api/routes/admin/orders/update-order.ts index afdad2065f..ff54f015a0 100644 --- a/packages/medusa/src/api/routes/admin/orders/update-order.ts +++ b/packages/medusa/src/api/routes/admin/orders/update-order.ts @@ -13,6 +13,7 @@ import { AddressPayload, FindParams } from "../../../../types/common" import { EntityManager } from "typeorm" import { OrderService } from "../../../../services" import { Type } from "class-transformer" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /orders/{id} @@ -96,7 +97,7 @@ export default async (req, res) => { includes: req.includes, }) - res.status(200).json({ order }) + res.status(200).json({ order: cleanResponseData(order, []) }) } /** diff --git a/packages/medusa/src/api/routes/store/carts/add-shipping-method.ts b/packages/medusa/src/api/routes/store/carts/add-shipping-method.ts index 4a95d190d9..949aa2bfdf 100644 --- a/packages/medusa/src/api/routes/store/carts/add-shipping-method.ts +++ b/packages/medusa/src/api/routes/store/carts/add-shipping-method.ts @@ -3,7 +3,7 @@ import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" import { EntityManager } from "typeorm" -import { validator } from "../../../../utils/validator" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/shipping-methods @@ -62,10 +62,7 @@ import { validator } from "../../../../utils/validator" export default async (req, res) => { const { id } = req.params - const validated = await validator( - StorePostCartsCartShippingMethodReq, - req.body - ) + const validated = req.validatedBody const manager: EntityManager = req.scope.resolve("manager") const cartService: CartService = req.scope.resolve("cartService") @@ -94,7 +91,7 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } /** diff --git a/packages/medusa/src/api/routes/store/carts/calculate-taxes.ts b/packages/medusa/src/api/routes/store/carts/calculate-taxes.ts index d9dc4969fa..feb15444ac 100644 --- a/packages/medusa/src/api/routes/store/carts/calculate-taxes.ts +++ b/packages/medusa/src/api/routes/store/carts/calculate-taxes.ts @@ -2,6 +2,7 @@ import { CartService, IdempotencyKeyService } from "../../../../services" import { EntityManager } from "typeorm" import { IdempotencyKey } from "../../../../models/idempotency-key" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/taxes @@ -118,5 +119,12 @@ export default async (req, res) => { throw err } + if (idempotencyKey.response_body.cart) { + idempotencyKey.response_body.cart = cleanResponseData( + idempotencyKey.response_body.cart, + [] + ) + } + res.status(idempotencyKey.response_code).json(idempotencyKey.response_body) } diff --git a/packages/medusa/src/api/routes/store/carts/complete-cart.ts b/packages/medusa/src/api/routes/store/carts/complete-cart.ts index ba4e945e3c..d35efe1e9f 100644 --- a/packages/medusa/src/api/routes/store/carts/complete-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/complete-cart.ts @@ -2,6 +2,7 @@ import { EntityManager } from "typeorm" import { AbstractCartCompletionStrategy } from "../../../../interfaces" import { IdempotencyKey } from "../../../../models" import { IdempotencyKeyService } from "../../../../services" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/complete @@ -90,5 +91,9 @@ export default async (req, res) => { req.request_context ) + if (response_body.data) { + response_body.data = cleanResponseData(response_body.data, []) + } + res.status(response_code).json(response_body) } diff --git a/packages/medusa/src/api/routes/store/carts/create-cart.ts b/packages/medusa/src/api/routes/store/carts/create-cart.ts index 6f98220412..0986bd43ce 100644 --- a/packages/medusa/src/api/routes/store/carts/create-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/create-cart.ts @@ -23,6 +23,7 @@ import { FlagRouter } from "../../../../utils/flag-router" import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-channels" import { CartCreateProps } from "../../../../types/cart" import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts @@ -176,7 +177,7 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart }) + res.status(200).json({ cart: cleanResponseData(cart, []) }) } export class Item { diff --git a/packages/medusa/src/api/routes/store/carts/create-line-item/index.ts b/packages/medusa/src/api/routes/store/carts/create-line-item/index.ts index ad866536a4..616db1079b 100644 --- a/packages/medusa/src/api/routes/store/carts/create-line-item/index.ts +++ b/packages/medusa/src/api/routes/store/carts/create-line-item/index.ts @@ -11,6 +11,7 @@ import { runIdempotencyStep, RunIdempotencyStepOptions, } from "../../../../../utils/idempotency" +import { cleanResponseData } from "../../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/line-items @@ -130,6 +131,13 @@ export default async (req, res) => { throw err } + if (idempotencyKey.response_body.cart) { + idempotencyKey.response_body.cart = cleanResponseData( + idempotencyKey.response_body.cart, + [] + ) + } + res.status(idempotencyKey.response_code).json(idempotencyKey.response_body) } diff --git a/packages/medusa/src/api/routes/store/carts/create-payment-sessions.ts b/packages/medusa/src/api/routes/store/carts/create-payment-sessions.ts index 73848816a6..9f5768fa4c 100644 --- a/packages/medusa/src/api/routes/store/carts/create-payment-sessions.ts +++ b/packages/medusa/src/api/routes/store/carts/create-payment-sessions.ts @@ -2,6 +2,7 @@ import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" import { EntityManager } from "typeorm" import IdempotencyKeyService from "../../../../services/idempotency-key" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/payment-sessions @@ -133,5 +134,11 @@ export default async (req, res) => { throw err } + if (idempotencyKey.response_body.cart) { + idempotencyKey.response_body.data = cleanResponseData( + idempotencyKey.response_body.cart, + [] + ) + } res.status(idempotencyKey.response_code).json(idempotencyKey.response_body) } diff --git a/packages/medusa/src/api/routes/store/carts/delete-discount.ts b/packages/medusa/src/api/routes/store/carts/delete-discount.ts index 7d2614b00c..4af4a7d91d 100644 --- a/packages/medusa/src/api/routes/store/carts/delete-discount.ts +++ b/packages/medusa/src/api/routes/store/carts/delete-discount.ts @@ -1,6 +1,7 @@ import { EntityManager } from "typeorm" import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [delete] /carts/{id}/discounts/{code} @@ -71,5 +72,5 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } diff --git a/packages/medusa/src/api/routes/store/carts/delete-line-item.ts b/packages/medusa/src/api/routes/store/carts/delete-line-item.ts index c1de836022..853600efa8 100644 --- a/packages/medusa/src/api/routes/store/carts/delete-line-item.ts +++ b/packages/medusa/src/api/routes/store/carts/delete-line-item.ts @@ -1,6 +1,7 @@ import { EntityManager } from "typeorm" import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [delete] /carts/{id}/line-items/{line_id} @@ -72,5 +73,6 @@ export default async (req, res) => { select: defaultStoreCartFields, relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + + res.status(200).json({ cart: cleanResponseData(data, []) }) } diff --git a/packages/medusa/src/api/routes/store/carts/delete-payment-session.ts b/packages/medusa/src/api/routes/store/carts/delete-payment-session.ts index 85fe988305..eed7d281d5 100644 --- a/packages/medusa/src/api/routes/store/carts/delete-payment-session.ts +++ b/packages/medusa/src/api/routes/store/carts/delete-payment-session.ts @@ -1,6 +1,7 @@ import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" import { EntityManager } from "typeorm" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [delete] /carts/{id}/payment-sessions/{provider_id} @@ -63,5 +64,5 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } diff --git a/packages/medusa/src/api/routes/store/carts/get-cart.ts b/packages/medusa/src/api/routes/store/carts/get-cart.ts index c441adb19d..99922ddb3e 100644 --- a/packages/medusa/src/api/routes/store/carts/get-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/get-cart.ts @@ -1,5 +1,6 @@ import { CartService } from "../../../../services" import { EntityManager } from "typeorm" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [get] /carts/{id} @@ -70,5 +71,5 @@ export default async (req, res) => { } const data = await cartService.retrieveWithTotals(id, req.retrieveConfig) - res.json({ cart: data }) + res.json({ cart: cleanResponseData(data, []) }) } diff --git a/packages/medusa/src/api/routes/store/carts/index.ts b/packages/medusa/src/api/routes/store/carts/index.ts index f9bb3b6c99..60c1757ca3 100644 --- a/packages/medusa/src/api/routes/store/carts/index.ts +++ b/packages/medusa/src/api/routes/store/carts/index.ts @@ -5,7 +5,7 @@ import { Cart, Order, Swap } from "../../../../" import { DeleteResponse, FindParams } from "../../../../types/common" import middlewares, { transformBody, - transformQuery, + transformStoreQuery, } from "../../../middlewares" import { StorePostCartsCartReq } from "./update-cart" import { StorePostCartReq } from "./create-cart" @@ -13,6 +13,10 @@ import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-cha import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys" import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params" import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param" +import { StorePostCartsCartShippingMethodReq } from "./add-shipping-method" +import { StorePostCartsCartPaymentSessionReq } from "./set-payment-session" +import { StorePostCartsCartLineItemsItemReq } from "./update-line-item" +import { StorePostCartsCartPaymentSessionUpdateReq } from "./update-payment-session" const route = Router() @@ -34,7 +38,7 @@ export default (app, container) => { route.get( "/:id", - transformQuery(FindParams, { + transformStoreQuery(FindParams, { defaultRelations: defaultStoreCartRelations, defaultFields: defaultStoreCartFields, isList: false, @@ -44,6 +48,11 @@ export default (app, container) => { const createMiddlewares = [ middlewareService.usePreCartCreation(), + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), transformBody(StorePostCartReq), ] @@ -62,75 +71,149 @@ export default (app, container) => { route.post( "/:id", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), transformBody(StorePostCartsCartReq), middlewares.wrap(require("./update-cart").default) ) route.post( "/:id/complete", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./complete-cart").default) ) // DEPRECATION route.post( "/:id/complete-cart", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./complete-cart").default) ) // Line items route.post( "/:id/line-items", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./create-line-item").default) ) route.post( "/:id/line-items/:line_id", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), + transformBody(StorePostCartsCartLineItemsItemReq), middlewares.wrap(require("./update-line-item").default) ) route.delete( "/:id/line-items/:line_id", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./delete-line-item").default) ) route.delete( "/:id/discounts/:code", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./delete-discount").default) ) // Payment sessions route.post( "/:id/payment-sessions", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./create-payment-sessions").default) ) route.post( "/:id/payment-sessions/:provider_id", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), + transformBody(StorePostCartsCartPaymentSessionUpdateReq), middlewares.wrap(require("./update-payment-session").default) ) route.delete( "/:id/payment-sessions/:provider_id", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./delete-payment-session").default) ) route.post( "/:id/payment-sessions/:provider_id/refresh", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./refresh-payment-session").default) ) route.post( "/:id/payment-session", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), + transformBody(StorePostCartsCartPaymentSessionReq), middlewares.wrap(require("./set-payment-session").default) ) // Shipping Options route.post( "/:id/shipping-methods", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), + transformBody(StorePostCartsCartShippingMethodReq), middlewares.wrap(require("./add-shipping-method").default) ) // Taxes route.post( "/:id/taxes", + transformStoreQuery(FindParams, { + defaultRelations: defaultStoreCartRelations, + defaultFields: defaultStoreCartFields, + isList: false, + }), middlewares.wrap(require("./calculate-taxes").default) ) diff --git a/packages/medusa/src/api/routes/store/carts/refresh-payment-session.ts b/packages/medusa/src/api/routes/store/carts/refresh-payment-session.ts index 17cc17e8a7..a56f07fa2e 100644 --- a/packages/medusa/src/api/routes/store/carts/refresh-payment-session.ts +++ b/packages/medusa/src/api/routes/store/carts/refresh-payment-session.ts @@ -1,5 +1,6 @@ import { CartService } from "../../../../services" import { EntityManager } from "typeorm" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/payment-sessions/{provider_id}/refresh @@ -67,5 +68,5 @@ export default async (req, res) => { ], }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } diff --git a/packages/medusa/src/api/routes/store/carts/set-payment-session.ts b/packages/medusa/src/api/routes/store/carts/set-payment-session.ts index cf80e04949..ba8743354d 100644 --- a/packages/medusa/src/api/routes/store/carts/set-payment-session.ts +++ b/packages/medusa/src/api/routes/store/carts/set-payment-session.ts @@ -3,7 +3,7 @@ import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" import { EntityManager } from "typeorm" import { IsString } from "class-validator" -import { validator } from "../../../../utils/validator" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/payment-session @@ -62,10 +62,7 @@ import { validator } from "../../../../utils/validator" export default async (req, res) => { const { id } = req.params - const validated = await validator( - StorePostCartsCartPaymentSessionReq, - req.body - ) + const validated = req.validatedBody const cartService: CartService = req.scope.resolve("cartService") @@ -81,7 +78,7 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } /** diff --git a/packages/medusa/src/api/routes/store/carts/update-cart.ts b/packages/medusa/src/api/routes/store/carts/update-cart.ts index 011e9c8c44..4930793efb 100644 --- a/packages/medusa/src/api/routes/store/carts/update-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/update-cart.ts @@ -14,6 +14,7 @@ import { CartService } from "../../../../services" import { AddressPayload } from "../../../../types/common" import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators" import { IsType } from "../../../../utils/validators/is-type" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id} @@ -100,7 +101,7 @@ export default async (req, res) => { select: defaultStoreCartFields, relations: defaultStoreCartRelations, }) - res.json({ cart: data }) + res.json({ cart: cleanResponseData(data, []) }) } class GiftCard { diff --git a/packages/medusa/src/api/routes/store/carts/update-line-item.ts b/packages/medusa/src/api/routes/store/carts/update-line-item.ts index d1a9d8d808..a25e99eddb 100644 --- a/packages/medusa/src/api/routes/store/carts/update-line-item.ts +++ b/packages/medusa/src/api/routes/store/carts/update-line-item.ts @@ -3,7 +3,7 @@ import { MedusaError } from "medusa-core-utils" import { EntityManager } from "typeorm" import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" -import { validator } from "../../../../utils/validator" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/line-items/{line_id} @@ -63,10 +63,7 @@ import { validator } from "../../../../utils/validator" export default async (req, res) => { const { id, line_id } = req.params - const validated = await validator( - StorePostCartsCartLineItemsItemReq, - req.body - ) + const validated = req.validatedBody const manager: EntityManager = req.scope.resolve("manager") const cartService: CartService = req.scope.resolve("cartService") @@ -115,7 +112,7 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } /** diff --git a/packages/medusa/src/api/routes/store/carts/update-payment-session.ts b/packages/medusa/src/api/routes/store/carts/update-payment-session.ts index e13d4290f0..b8efc772c0 100644 --- a/packages/medusa/src/api/routes/store/carts/update-payment-session.ts +++ b/packages/medusa/src/api/routes/store/carts/update-payment-session.ts @@ -1,8 +1,8 @@ import { IsObject } from "class-validator" import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" -import { validator } from "../../../../utils/validator" import { EntityManager } from "typeorm" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [post] /carts/{id}/payment-sessions/{provider_id} @@ -64,10 +64,7 @@ import { EntityManager } from "typeorm" export default async (req, res) => { const { id, provider_id } = req.params - const validated = await validator( - StorePostCartsCartPaymentSessionUpdateReq, - req.body - ) + const validated = req.validatedBody const cartService: CartService = req.scope.resolve("cartService") @@ -86,7 +83,7 @@ export default async (req, res) => { relations: defaultStoreCartRelations, }) - res.status(200).json({ cart: data }) + res.status(200).json({ cart: cleanResponseData(data, []) }) } /** diff --git a/packages/medusa/src/api/routes/store/collections/index.ts b/packages/medusa/src/api/routes/store/collections/index.ts index 823d2803da..7d16f8bf13 100644 --- a/packages/medusa/src/api/routes/store/collections/index.ts +++ b/packages/medusa/src/api/routes/store/collections/index.ts @@ -1,7 +1,7 @@ import { Router } from "express" import { PaginatedResponse } from "../../../../types/common" import { ProductCollection } from "../../../../" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import { StoreGetCollectionsParams } from "./list-collections" const route = Router() @@ -11,7 +11,7 @@ export default (app) => { route.get( "/", - transformQuery(StoreGetCollectionsParams, { + transformStoreQuery(StoreGetCollectionsParams, { allowedFields, isList: true, }), diff --git a/packages/medusa/src/api/routes/store/customers/index.ts b/packages/medusa/src/api/routes/store/customers/index.ts index 15c22e03f4..5d13611c26 100644 --- a/packages/medusa/src/api/routes/store/customers/index.ts +++ b/packages/medusa/src/api/routes/store/customers/index.ts @@ -1,7 +1,7 @@ import { Router } from "express" import { Customer, Order } from "../../../.." import { PaginatedResponse } from "../../../../types/common" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import { defaultStoreOrdersFields, defaultStoreOrdersRelations, @@ -41,7 +41,7 @@ export default (app, container) => { route.get( "/me/orders", - transformQuery(StoreGetCustomersCustomerOrdersParams, { + transformStoreQuery(StoreGetCustomersCustomerOrdersParams, { defaultFields: defaultStoreOrdersFields, defaultRelations: defaultStoreOrdersRelations, isList: true, diff --git a/packages/medusa/src/api/routes/store/order-edits/index.ts b/packages/medusa/src/api/routes/store/order-edits/index.ts index de1753d109..1ef3d29ccd 100644 --- a/packages/medusa/src/api/routes/store/order-edits/index.ts +++ b/packages/medusa/src/api/routes/store/order-edits/index.ts @@ -7,7 +7,7 @@ import { } from "../../../../types/order-edit" import middlewares, { transformBody, - transformQuery, + transformStoreQuery, } from "../../../middlewares" import { StorePostOrderEditsOrderEditDecline } from "./decline-order-edit" @@ -18,7 +18,7 @@ export default (app) => { route.get( "/:id", - transformQuery(FindParams, { + transformStoreQuery(FindParams, { defaultRelations: defaultStoreOrderEditRelations, defaultFields: defaultStoreOrderEditFields, allowedFields: defaultStoreOrderEditFields, diff --git a/packages/medusa/src/api/routes/store/orders/get-order-by-cart.ts b/packages/medusa/src/api/routes/store/orders/get-order-by-cart.ts index d97d7e64ee..1048b33d89 100644 --- a/packages/medusa/src/api/routes/store/orders/get-order-by-cart.ts +++ b/packages/medusa/src/api/routes/store/orders/get-order-by-cart.ts @@ -1,6 +1,7 @@ import { defaultStoreOrdersFields, defaultStoreOrdersRelations } from "." import { OrderService } from "../../../../services" +import { cleanResponseData } from "../../../../utils/clean-response-data" /** * @oas [get] /orders/cart/{cart_id} @@ -54,5 +55,5 @@ export default async (req, res) => { relations: defaultStoreOrdersRelations, }) - res.json({ order }) + res.json({ order: cleanResponseData(order, []) }) } diff --git a/packages/medusa/src/api/routes/store/orders/index.ts b/packages/medusa/src/api/routes/store/orders/index.ts index 7ece67b6fa..5e5d086769 100644 --- a/packages/medusa/src/api/routes/store/orders/index.ts +++ b/packages/medusa/src/api/routes/store/orders/index.ts @@ -3,13 +3,14 @@ import "reflect-metadata" import { Order } from "../../../.." import middlewares, { transformBody, - transformQuery, + transformStoreQuery, } from "../../../middlewares" import requireCustomerAuthentication from "../../../middlewares/require-customer-authentication" import { StorePostCustomersCustomerOrderClaimReq } from "./request-order" import { StorePostCustomersCustomerAcceptClaimReq } from "./confirm-order-request" import { StoreGetOrderParams } from "./get-order" import { StoreGetOrdersParams } from "./lookup-order" +import { FindParams } from "../../../../types/common" const route = Router() @@ -21,7 +22,7 @@ export default (app) => { */ route.get( "/", - transformQuery(StoreGetOrdersParams, { + transformStoreQuery(StoreGetOrdersParams, { defaultFields: defaultStoreOrdersFields, defaultRelations: defaultStoreOrdersRelations, allowedFields: allowedStoreOrdersFields, @@ -36,7 +37,7 @@ export default (app) => { */ route.get( "/:id", - transformQuery(StoreGetOrderParams, { + transformStoreQuery(StoreGetOrderParams, { defaultFields: defaultStoreOrdersFields, defaultRelations: defaultStoreOrdersRelations, allowedFields: allowedStoreOrdersFields, @@ -50,6 +51,12 @@ export default (app) => { */ route.get( "/cart/:cart_id", + transformStoreQuery(FindParams, { + defaultFields: defaultStoreOrdersFields, + defaultRelations: defaultStoreOrdersRelations, + allowedFields: allowedStoreOrdersFields, + allowedRelations: allowedStoreOrdersRelations, + }), middlewares.wrap(require("./get-order-by-cart").default) ) diff --git a/packages/medusa/src/api/routes/store/payment-collections/index.ts b/packages/medusa/src/api/routes/store/payment-collections/index.ts index 1e7d521b40..b8d7c4f7b2 100644 --- a/packages/medusa/src/api/routes/store/payment-collections/index.ts +++ b/packages/medusa/src/api/routes/store/payment-collections/index.ts @@ -2,7 +2,7 @@ import { Router } from "express" import "reflect-metadata" import middlewares, { transformBody, - transformQuery, + transformStoreQuery, } from "../../../middlewares" import { PaymentCollection, PaymentSession } from "../../../../models" @@ -18,7 +18,7 @@ export default (app, container) => { route.get( "/:id", - transformQuery(GetPaymentCollectionsParams, { + transformStoreQuery(GetPaymentCollectionsParams, { defaultFields: defaultPaymentCollectionFields, defaultRelations: defaultPaymentCollectionRelations, isList: false, diff --git a/packages/medusa/src/api/routes/store/product-categories/index.ts b/packages/medusa/src/api/routes/store/product-categories/index.ts index 6b75789879..3b297a3b07 100644 --- a/packages/medusa/src/api/routes/store/product-categories/index.ts +++ b/packages/medusa/src/api/routes/store/product-categories/index.ts @@ -1,5 +1,5 @@ import { Router } from "express" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import { ProductCategory } from "../../../../models" import { PaginatedResponse } from "../../../../types/common" @@ -18,7 +18,7 @@ export default (app) => { route.get( "/", - transformQuery(StoreGetProductCategoriesParams, { + transformStoreQuery(StoreGetProductCategoriesParams, { defaultFields: defaultStoreProductCategoryFields, allowedFields: allowedStoreProductCategoryFields, defaultRelations: defaultStoreProductCategoryRelations, @@ -29,7 +29,7 @@ export default (app) => { route.get( "/:id", - transformQuery(StoreGetProductCategoryParams, { + transformStoreQuery(StoreGetProductCategoryParams, { defaultFields: defaultStoreProductCategoryFields, allowedFields: allowedStoreProductCategoryFields, defaultRelations: defaultStoreProductCategoryRelations, diff --git a/packages/medusa/src/api/routes/store/product-tags/index.ts b/packages/medusa/src/api/routes/store/product-tags/index.ts index b1ebd18390..ad0c730ffd 100644 --- a/packages/medusa/src/api/routes/store/product-tags/index.ts +++ b/packages/medusa/src/api/routes/store/product-tags/index.ts @@ -1,7 +1,7 @@ import { Router } from "express" import { ProductTag } from "../../../../models" import { PaginatedResponse } from "../../../../types/common" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import { StoreGetProductTagsParams } from "./list-product-tags" const route = Router() @@ -11,7 +11,7 @@ export default (app: Router) => { route.get( "/", - transformQuery(StoreGetProductTagsParams, { + transformStoreQuery(StoreGetProductTagsParams, { defaultFields: defaultStoreProductTagFields, defaultRelations: defaultStoreProductTagRelations, allowedFields: allowedStoreProductTagFields, diff --git a/packages/medusa/src/api/routes/store/product-types/index.ts b/packages/medusa/src/api/routes/store/product-types/index.ts index fae449a4b3..fdb99ba702 100644 --- a/packages/medusa/src/api/routes/store/product-types/index.ts +++ b/packages/medusa/src/api/routes/store/product-types/index.ts @@ -1,7 +1,7 @@ import { Router } from "express" import { ProductType } from "../../../.." import { PaginatedResponse } from "../../../../types/common" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import "reflect-metadata" import { StoreGetProductTypesParams } from "./list-product-types" @@ -12,7 +12,7 @@ export default (app) => { route.get( "/", - transformQuery(StoreGetProductTypesParams, { + transformStoreQuery(StoreGetProductTypesParams, { defaultFields: defaultStoreProductTypeFields, defaultRelations: defaultStoreProductTypeRelations, allowedFields: allowedStoreProductTypeFields, diff --git a/packages/medusa/src/api/routes/store/products/index.ts b/packages/medusa/src/api/routes/store/products/index.ts index 784c50d9c6..44098022b6 100644 --- a/packages/medusa/src/api/routes/store/products/index.ts +++ b/packages/medusa/src/api/routes/store/products/index.ts @@ -2,7 +2,7 @@ import { RequestHandler, Router } from "express" import "reflect-metadata" import { Product } from "../../../.." -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { transformStoreQuery } from "../../../middlewares" import { FlagRouter } from "../../../../utils/flag-router" import { PaginatedResponse } from "../../../../types/common" import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params" @@ -28,7 +28,7 @@ export default (app, featureFlagRouter: FlagRouter) => { route.get( "/", - transformQuery(StoreGetProductsParams, { + transformStoreQuery(StoreGetProductsParams, { defaultRelations: defaultStoreProductsRelations, defaultFields: defaultStoreProductsFields, allowedFields: allowedStoreProductsFields, @@ -40,7 +40,7 @@ export default (app, featureFlagRouter: FlagRouter) => { route.get( "/:id", - transformQuery(StoreGetProductsProductParams, { + transformStoreQuery(StoreGetProductsProductParams, { defaultRelations: defaultStoreProductsRelations, defaultFields: defaultStoreProductsFields, allowedFields: allowedStoreProductsFields, diff --git a/packages/medusa/src/interfaces/cart-completion-strategy.ts b/packages/medusa/src/interfaces/cart-completion-strategy.ts index c28dc849be..236d8d4cb4 100644 --- a/packages/medusa/src/interfaces/cart-completion-strategy.ts +++ b/packages/medusa/src/interfaces/cart-completion-strategy.ts @@ -1,13 +1,12 @@ import { IdempotencyKey } from "../models" import { RequestContext } from "../types/request" -import { TransactionBaseService } from "./transaction-base-service" export type CartCompletionResponse = { /** The response code for the completion request */ response_code: number /** The response body for the completion request */ - response_body: object + response_body: Record } export interface ICartCompletionStrategy { diff --git a/packages/medusa/src/migrations/1678093365812-line-item-adjustments-amount.ts b/packages/medusa/src/migrations/1678093365812-line-item-adjustments-amount.ts new file mode 100644 index 0000000000..93ed4bd95c --- /dev/null +++ b/packages/medusa/src/migrations/1678093365812-line-item-adjustments-amount.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class lineItemAdjustmentsAmount1678093365812 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE line_item_adjustment ALTER COLUMN amount TYPE NUMERIC; + `) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE line_item_adjustment ALTER COLUMN amount TYPE integer; + `) + } +} diff --git a/packages/medusa/src/models/cart.ts b/packages/medusa/src/models/cart.ts index 026d820c96..0b83563ed9 100644 --- a/packages/medusa/src/models/cart.ts +++ b/packages/medusa/src/models/cart.ts @@ -170,6 +170,10 @@ * type: integer * example: 1000 * discount_total: + * description: The total of discount rounded + * type: integer + * example: 800 + * raw_discount_total: * description: The total of discount * type: integer * example: 800 @@ -376,6 +380,7 @@ export class Cart extends SoftDeletableEntity { shipping_total?: number discount_total?: number + raw_discount_total?: number item_tax_total?: number | null shipping_tax_total?: number | null tax_total?: number | null diff --git a/packages/medusa/src/models/line-item-adjustment.ts b/packages/medusa/src/models/line-item-adjustment.ts index 8a4f2edd43..af0245dc8b 100644 --- a/packages/medusa/src/models/line-item-adjustment.ts +++ b/packages/medusa/src/models/line-item-adjustment.ts @@ -8,10 +8,9 @@ import { PrimaryColumn, } from "typeorm" -import { DbAwareColumn } from "../utils/db-aware-column" +import { DbAwareColumn, generateEntityId } from "../utils" import { Discount } from "./discount" import { LineItem } from "./line-item" -import { generateEntityId } from "../utils/generate-entity-id" @Entity() @Index(["discount_id", "item_id"], { @@ -41,7 +40,7 @@ export class LineItemAdjustment { @Column({ nullable: true }) discount_id: string - @Column({ type: "int" }) + @Column({ type: "numeric", transformer: { to: (value) => value, from: (value) => parseFloat(value) } }) amount: number @DbAwareColumn({ type: "jsonb", nullable: true }) @@ -93,7 +92,7 @@ export class LineItemAdjustment { * $ref: "#/components/schemas/Discount" * amount: * description: The adjustment amount - * type: integer + * type: number * example: 1000 * metadata: * description: An optional key-value map with additional details diff --git a/packages/medusa/src/models/line-item.ts b/packages/medusa/src/models/line-item.ts index ef51aab919..75f981af1e 100644 --- a/packages/medusa/src/models/line-item.ts +++ b/packages/medusa/src/models/line-item.ts @@ -10,7 +10,8 @@ import { } from "typeorm" import { BaseEntity } from "../interfaces" -import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing" +import TaxInclusivePricingFeatureFlag + from "../loaders/feature-flags/tax-inclusive-pricing" import { generateEntityId } from "../utils" import { DbAwareColumn } from "../utils/db-aware-column" import { FeatureFlagColumn } from "../utils/feature-flag-decorators" @@ -147,6 +148,7 @@ export class LineItem extends BaseEntity { original_total?: number | null original_tax_total?: number | null discount_total?: number | null + raw_discount_total?: number | null gift_card_total?: number | null @BeforeInsert() @@ -341,6 +343,10 @@ export class LineItem extends BaseEntity { * type: integer * example: 0 * discount_total: + * description: The total of discount of the line item rounded + * type: integer + * example: 0 + * raw_discount_total: * description: The total of discount of the line item * type: integer * example: 0 diff --git a/packages/medusa/src/models/order.ts b/packages/medusa/src/models/order.ts index f0bbc72758..c0873cb6ea 100644 --- a/packages/medusa/src/models/order.ts +++ b/packages/medusa/src/models/order.ts @@ -248,6 +248,7 @@ export class Order extends BaseEntity { // Total fields shipping_total: number discount_total: number + raw_discount_total: number tax_total: number | null refunded_total: number total: number @@ -513,10 +514,14 @@ export class Order extends BaseEntity { * type: integer * description: The total of shipping * example: 1000 - * discount_total: + * raw_discount_total: * description: The total of discount * type: integer * example: 800 + * discount_total: + * description: The total of discount rounded + * type: integer + * example: 800 * tax_total: * description: The total of tax * type: integer diff --git a/packages/medusa/src/services/__tests__/discount.js b/packages/medusa/src/services/__tests__/discount.js index 8782c77a69..03378f61ee 100644 --- a/packages/medusa/src/services/__tests__/discount.js +++ b/packages/medusa/src/services/__tests__/discount.js @@ -737,8 +737,9 @@ describe("DiscountService", () => { } ) - expect(adjustment1).toBe(291) - expect(adjustment2).toBe(109) + // The sum of both is equal to the expected 400 + expect(adjustment1).toBeCloseTo(291, 0) + expect(adjustment2).toBeCloseTo(109, 0) }) it("returns line item amount if discount exceeds lime item price", async () => { diff --git a/packages/medusa/src/services/__tests__/order.js b/packages/medusa/src/services/__tests__/order.js index c02623bc94..44828445b3 100644 --- a/packages/medusa/src/services/__tests__/order.js +++ b/packages/medusa/src/services/__tests__/order.js @@ -1345,6 +1345,7 @@ describe("OrderService", () => { id: IdMap.getId("order"), items: [], paid_total: 0, + raw_discount_total: 0, refundable_amount: 0, refunded_total: 0, shipping_methods: [ @@ -1384,6 +1385,7 @@ describe("OrderService", () => { id: IdMap.getId("order"), items: [], paid_total: 0, + raw_discount_total: 0, refundable_amount: 0, refunded_total: 0, shipping_methods: [ diff --git a/packages/medusa/src/services/cart.ts b/packages/medusa/src/services/cart.ts index 903483694b..f51d56f632 100644 --- a/packages/medusa/src/services/cart.ts +++ b/packages/medusa/src/services/cart.ts @@ -2577,7 +2577,7 @@ class CartService extends TransactionBaseService { const itemWithTotals = Object.assign(item, itemsTotals[item.id] ?? {}) cart.subtotal! += itemWithTotals.subtotal ?? 0 - cart.discount_total! += itemWithTotals.discount_total ?? 0 + cart.discount_total! += itemWithTotals.raw_discount_total ?? 0 cart.item_tax_total! += itemWithTotals.tax_total ?? 0 return itemWithTotals @@ -2604,10 +2604,15 @@ class CartService extends TransactionBaseService { giftCards: cart.gift_cards, } ) + cart.gift_card_total = giftCardTotal.total || 0 cart.gift_card_tax_total = giftCardTotal.tax_total || 0 cart.tax_total = cart.item_tax_total + cart.shipping_tax_total + cart.discount_total = Math.round(cart.discount_total) + + cart.raw_discount_total = cart.discount_total + cart.discount_total = Math.round(cart.discount_total) cart.total = cart.subtotal + diff --git a/packages/medusa/src/services/discount.ts b/packages/medusa/src/services/discount.ts index c6c1805344..657d9e848f 100644 --- a/packages/medusa/src/services/discount.ts +++ b/packages/medusa/src/services/discount.ts @@ -634,7 +634,10 @@ class DiscountService extends TransactionBaseService { }) let fullItemPrice = lineItem.unit_price * lineItem.quantity - const includesTax = this.featureFlagRouter_.isFeatureEnabled(TaxInclusivePricingFeatureFlag.key) && lineItem.includes_tax + const includesTax = + this.featureFlagRouter_.isFeatureEnabled( + TaxInclusivePricingFeatureFlag.key + ) && lineItem.includes_tax if (includesTax) { const lineItemTotals = await this.newTotalsService_ @@ -671,14 +674,13 @@ class DiscountService extends TransactionBaseService { }, 0) const nominator = Math.min(value, subtotal) const totalItemPercentage = fullItemPrice / subtotal - adjustment = Math.round(nominator * totalItemPercentage) + + adjustment = nominator * totalItemPercentage } else { adjustment = value * lineItem.quantity } - // if the amount of the discount exceeds the total price of the item, - // we return the total item price, else the fixed amount - return adjustment >= fullItemPrice ? fullItemPrice : adjustment + return Math.min(adjustment, fullItemPrice) }) } diff --git a/packages/medusa/src/services/new-totals.ts b/packages/medusa/src/services/new-totals.ts index ccc7b3d782..15b1110ac1 100644 --- a/packages/medusa/src/services/new-totals.ts +++ b/packages/medusa/src/services/new-totals.ts @@ -31,6 +31,8 @@ type LineItemTotals = { original_tax_total: number tax_lines: LineItemTaxLine[] discount_total: number + + raw_discount_total: number } type GiftCardTransaction = { @@ -172,7 +174,8 @@ export default class NewTotalsService extends TransactionBaseService { subtotal = 0 // in that case we need to know the tax rate to compute it later } - const discount_total = lineItemAllocation.discount?.amount ?? 0 + const raw_discount_total = lineItemAllocation.discount?.amount ?? 0 + const discount_total = Math.round(raw_discount_total) const totals: LineItemTotals = { unit_price: item.unit_price, @@ -184,6 +187,8 @@ export default class NewTotalsService extends TransactionBaseService { original_tax_total: 0, tax_total: 0, tax_lines: item.tax_lines ?? [], + + raw_discount_total: raw_discount_total, } if (includeTax) { @@ -274,7 +279,8 @@ export default class NewTotalsService extends TransactionBaseService { subtotal = 0 // in that case we need to know the tax rate to compute it later } - const discount_total = lineItemAllocation.discount?.amount ?? 0 + const raw_discount_total = lineItemAllocation.discount?.amount ?? 0 + const discount_total = Math.round(raw_discount_total) const totals: LineItemTotals = { unit_price: item.unit_price, @@ -286,6 +292,8 @@ export default class NewTotalsService extends TransactionBaseService { original_tax_total: 0, tax_total: 0, tax_lines: [], + + raw_discount_total, } taxRate = taxRate / 100 diff --git a/packages/medusa/src/services/order.ts b/packages/medusa/src/services/order.ts index 7490ed7c93..cb05e21456 100644 --- a/packages/medusa/src/services/order.ts +++ b/packages/medusa/src/services/order.ts @@ -17,14 +17,14 @@ import { PaymentStatus, Return, Swap, - TrackingLink + TrackingLink, } from "../models" import { AddressRepository } from "../repositories/address" import { OrderRepository } from "../repositories/order" import { FindConfig, QuerySelector, Selector } from "../types/common" import { CreateFulfillmentOrder, - FulFillmentItemType + FulFillmentItemType, } from "../types/fulfillment" import { TotalsContext, UpdateOrderInput } from "../types/orders" import { CreateShippingMethodDto } from "../types/shipping-options" @@ -48,7 +48,7 @@ import { ShippingOptionService, ShippingProfileService, TaxProviderService, - TotalsService + TotalsService, } from "." export const ORDER_CART_ALREADY_EXISTS_ERROR = "Order from cart already exists" @@ -1777,6 +1777,7 @@ class OrderService extends TransactionBaseService { order.paid_total = order.payments?.reduce((acc, next) => (acc += next.amount), 0) || 0 order.refundable_amount = order.paid_total - order.refunded_total || 0 + let item_tax_total = 0 let shipping_tax_total = 0 @@ -1790,7 +1791,7 @@ class OrderService extends TransactionBaseService { Object.assign(item, itemsTotals[item.id] ?? {}, { refundable }) order.subtotal += item.subtotal ?? 0 - order.discount_total += item.discount_total ?? 0 + order.discount_total += item.raw_discount_total ?? 0 item_tax_total += item.tax_total ?? 0 if (isReturnableItem(item)) { @@ -1864,6 +1865,9 @@ class OrderService extends TransactionBaseService { }) } + order.raw_discount_total = order.discount_total + order.discount_total = Math.round(order.discount_total) + order.total = order.subtotal + order.shipping_total + diff --git a/packages/medusa/src/services/totals.ts b/packages/medusa/src/services/totals.ts index dfc3d1606c..542c5f3d07 100644 --- a/packages/medusa/src/services/totals.ts +++ b/packages/medusa/src/services/totals.ts @@ -58,6 +58,8 @@ type LineItemTotals = { original_tax_total: number tax_lines: LineItemTaxLine[] discount_total: number + + raw_discount_total: number } type LineItemTotalsOptions = { @@ -465,7 +467,7 @@ class TotalsService extends TransactionBaseService { /** * Used for the refund computation */ - unit_amount: Math.round(adjustmentAmount / ld.item.quantity), + unit_amount: adjustmentAmount / ld.item.quantity, } } else { allocationMap[ld.item.id] = { @@ -800,7 +802,8 @@ class TotalsService extends TransactionBaseService { subtotal = 0 // in that case we need to know the tax rate to compute it later } - const discount_total = lineItemAllocation.discount?.amount ?? 0 + const raw_discount_total = lineItemAllocation.discount?.amount ?? 0 + const discount_total = Math.round(raw_discount_total) const lineItemTotals: LineItemTotals = { unit_price: lineItem.unit_price, @@ -812,6 +815,8 @@ class TotalsService extends TransactionBaseService { original_tax_total: 0, tax_total: 0, tax_lines: lineItem.tax_lines || [], + + raw_discount_total, } // Tax Information @@ -1007,7 +1012,9 @@ class TotalsService extends TransactionBaseService { excludeNonDiscounts: true, }) - const discountTotal = this.getLineItemAdjustmentsTotal(cartOrOrder) + const discountTotal = Math.round( + this.getLineItemAdjustmentsTotal(cartOrOrder) + ) if (subtotal < 0) { return this.rounded(Math.max(subtotal, discountTotal)) diff --git a/packages/medusa/src/types/global.ts b/packages/medusa/src/types/global.ts index cf0d08bde5..248e59287a 100644 --- a/packages/medusa/src/types/global.ts +++ b/packages/medusa/src/types/global.ts @@ -18,6 +18,7 @@ declare global { retrieveConfig: FindConfig filterableFields: Record allowedProperties: string[] + includes?: Record errors: string[] } } diff --git a/packages/medusa/src/utils/__tests__/omit-deep.spec.ts b/packages/medusa/src/utils/__tests__/omit-deep.spec.ts new file mode 100644 index 0000000000..53dd214b9c --- /dev/null +++ b/packages/medusa/src/utils/__tests__/omit-deep.spec.ts @@ -0,0 +1,59 @@ +import { omitDeep } from "../omit-deep" + +describe("omitDeep", () => { + it("should omit properties in a nested object", () => { + const input = { + id: 1, + __typename: "123", + createdAt: "1020209", + address: { + id: 1, + __typename: "123", + }, + variants: [ + 20, + { + id: 22, + title: "hello world", + __typename: "123", + createdAt: "1020209", + variantOption: { + id: 1, + __typename: "123", + }, + }, + { + id: 32, + test: null, + __typename: "123", + createdAt: "1020209", + }, + ], + } + + const output = { + id: 1, + address: { + id: 1, + }, + variants: [ + 20, + { + id: 22, + title: "hello world", + variantOption: { + id: 1, + }, + }, + { + id: 32, + test: null, + }, + ], + } + + expect( + omitDeep(input, ["createdAt", "updatedAt", "__typename"]) + ).toEqual(output) + }) +}) \ No newline at end of file diff --git a/packages/medusa/src/utils/clean-response-data.ts b/packages/medusa/src/utils/clean-response-data.ts index cca1002f7f..b9ce0f4454 100644 --- a/packages/medusa/src/utils/clean-response-data.ts +++ b/packages/medusa/src/utils/clean-response-data.ts @@ -1,21 +1,64 @@ import { pick } from "lodash" +import { omitDeep } from "./omit-deep" + +// TODO: once the legacy totals decoration will be removed. +// We will be able to only compute the totals if one of the total fields is present +// and therefore avoid totals computation if the user don't want them to appear in the response +// and therefore the below const will be removed +const INCLUDED_FIELDS = [ + "shipping_total", + "discount_total", + "tax_total", + "refunded_total", + "total", + "subtotal", + "paid_total", + "refundable_amount", + "gift_card_total", + "gift_card_tax_total", + "item_tax_total", + "shipping_tax_total", + "refundable", + "original_total", + "original_tax_total", +] + +const EXCLUDED_FIELDS = ["raw_discount_total"] /** - * Filter response data to contain props specified in the fields array. + * Filter response data to contain props specified in the `allowedProperties`. + * You can read more in the transformQuery middleware utility methods. * * @param data - record or an array of records in the response * @param fields - record props allowed in the response */ -function cleanResponseData(data: T, fields: string[]) { +function cleanResponseData( + data: T, + fields: string[] +): T extends [] ? Partial[] : Partial { + fields = fields ?? [] + + const isDataArray = Array.isArray(data) + let arrayData: Partial[] = isDataArray ? data : [data] + if (!fields.length) { - return data + arrayData = arrayData.map((record) => omitDeep(record, EXCLUDED_FIELDS)) + return (isDataArray ? arrayData : arrayData[0]) as T extends [] + ? Partial[] + : Partial } - if (Array.isArray(data)) { - return data.map((record) => pick(record, fields)) - } + const fieldsSet = new Set([...fields, ...INCLUDED_FIELDS]) - return pick(data, fields) + fields = [...fieldsSet] + + arrayData = arrayData.map((record) => + pick(omitDeep(record, EXCLUDED_FIELDS), fields) + ) + + return (isDataArray ? arrayData : arrayData[0]) as T extends [] + ? Partial[] + : Partial } export { cleanResponseData } diff --git a/packages/medusa/src/utils/index.ts b/packages/medusa/src/utils/index.ts index 432bf399c8..99f6c35b7f 100644 --- a/packages/medusa/src/utils/index.ts +++ b/packages/medusa/src/utils/index.ts @@ -10,3 +10,4 @@ export * from "./exception-formatter" export * from "./db-aware-column" export * from "./is-object" export * from "./has-changes" +export * from "./omit-deep" diff --git a/packages/medusa/src/utils/is-object.ts b/packages/medusa/src/utils/is-object.ts index 778a601412..e577671adc 100644 --- a/packages/medusa/src/utils/is-object.ts +++ b/packages/medusa/src/utils/is-object.ts @@ -1,3 +1,3 @@ -export function isObject(obj: unknown): obj is object { - return typeof obj === "object" && !!obj +export function isObject(obj: any): obj is object { + return obj != null && obj?.constructor?.name === "Object" } diff --git a/packages/medusa/src/utils/omit-deep.ts b/packages/medusa/src/utils/omit-deep.ts new file mode 100644 index 0000000000..a86453c0a7 --- /dev/null +++ b/packages/medusa/src/utils/omit-deep.ts @@ -0,0 +1,34 @@ +import { isObject } from "./is-object" + +export function omitDeep( + input: object, + excludes: Array +): T { + if (!input) { + return input + } + + return Object.entries(input).reduce((nextInput, [key, value]) => { + const shouldExclude = excludes.includes(key) + if (shouldExclude) { + return nextInput + } + + if (Array.isArray(value)) { + nextInput[key] = value.map((arrItem) => { + if (isObject(arrItem)) { + return omitDeep(arrItem, excludes) + } + return arrItem + }) + return nextInput + } else if (isObject(value)) { + nextInput[key] = omitDeep(value, excludes) + return nextInput + } + + nextInput[key] = value + + return nextInput + }, {} as T) +}