fix(medusa): Rounding issues on line item adjustments (#3446)
* chores(medusa): Attempt to fix discount rounding issues * add migration * update entities * apply multipler factor properly * fix discount service * WIP * fix rounding issues in discounts * fix some tests * Exclude raw_discount_total from responses * fix adjustments * cleanup response * fix * fix draft order integration * fix order integration * fix order integration * address feedback * fix test * Create .changeset/polite-llamas-sit.md * remove comment --------- Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
co-authored by
Oliver Windall Juhl
parent
577098a4db
commit
d886430bf8
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/medusa": patch
|
||||
---
|
||||
|
||||
fix(medusa): Rounding issues on line item adjustments
|
||||
@@ -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,
|
||||
}),
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
|
||||
@@ -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",
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -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",
|
||||
])
|
||||
})
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<T>,
|
||||
queryConfig?: Omit<
|
||||
QueryConfig<TEntity>,
|
||||
"allowedRelations" | "allowedFields"
|
||||
>,
|
||||
config: ValidatorOptions = {}
|
||||
): (req: Request, res: Response, next: NextFunction) => Promise<void> {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
normalizeQuery()(req, res, () => void 0)
|
||||
const validated: T = await validator<T, Record<string, unknown>>(
|
||||
plainToClass,
|
||||
req.query,
|
||||
config
|
||||
)
|
||||
req.validatedQuery = validated
|
||||
req.filterableFields = getFilterableFields(validated)
|
||||
req.allowedProperties = getAllowedProperties(
|
||||
validated,
|
||||
req.includes ?? {},
|
||||
queryConfig
|
||||
)
|
||||
attachListOrRetrieveConfig<TEntity>(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<T>,
|
||||
queryConfig?: QueryConfig<TEntity>,
|
||||
@@ -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<unknown>
|
||||
} else {
|
||||
req.retrieveConfig = prepareRetrieveQuery(
|
||||
validated,
|
||||
queryConfig
|
||||
) as FindConfig<unknown>
|
||||
}
|
||||
req.filterableFields = getFilterableFields(validated)
|
||||
req.allowedProperties = getStoreAllowedProperties(
|
||||
validated,
|
||||
req.includes ?? {},
|
||||
queryConfig
|
||||
)
|
||||
attachListOrRetrieveConfig<TEntity>(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<T extends RequestQueryFields>(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<TEntity extends BaseEntity>(
|
||||
req: Request,
|
||||
queryConfig?: QueryConfig<TEntity>
|
||||
) {
|
||||
const validated = req.validatedQuery
|
||||
if (queryConfig?.isList) {
|
||||
req.listConfig = prepareListQuery(
|
||||
validated,
|
||||
queryConfig
|
||||
) as FindConfig<unknown>
|
||||
} else {
|
||||
req.retrieveConfig = prepareRetrieveQuery(
|
||||
validated,
|
||||
queryConfig
|
||||
) as FindConfig<unknown>
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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<TEntity extends BaseEntity>(
|
||||
validated: RequestQueryFields,
|
||||
includesOptions: Record<string, boolean>,
|
||||
queryConfig?: QueryConfig<TEntity>
|
||||
): 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<TEntity extends BaseEntity>(
|
||||
validated: RequestQueryFields,
|
||||
includesOptions: Record<string, boolean>,
|
||||
queryConfig?: QueryConfig<TEntity>
|
||||
): 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[]
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, []),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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, []),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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, []),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []),
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []),
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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, []) })
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
export interface ICartCompletionStrategy {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class lineItemAdjustmentsAmount1678093365812 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE line_item_adjustment ALTER COLUMN amount TYPE NUMERIC;
|
||||
`)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE line_item_adjustment ALTER COLUMN amount TYPE integer;
|
||||
`)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -18,6 +18,7 @@ declare global {
|
||||
retrieveConfig: FindConfig<unknown>
|
||||
filterableFields: Record<string, unknown>
|
||||
allowedProperties: string[]
|
||||
includes?: Record<string, boolean>
|
||||
errors: string[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
@@ -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<T>(data: T, fields: string[]) {
|
||||
function cleanResponseData<T extends unknown | unknown[]>(
|
||||
data: T,
|
||||
fields: string[]
|
||||
): T extends [] ? Partial<T>[] : Partial<T> {
|
||||
fields = fields ?? []
|
||||
|
||||
const isDataArray = Array.isArray(data)
|
||||
let arrayData: Partial<T>[] = 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<T>[]
|
||||
: Partial<T>
|
||||
}
|
||||
|
||||
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<T>[]
|
||||
: Partial<T>
|
||||
}
|
||||
|
||||
export { cleanResponseData }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { isObject } from "./is-object"
|
||||
|
||||
export function omitDeep<T extends object = object>(
|
||||
input: object,
|
||||
excludes: Array<number | string>
|
||||
): 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)
|
||||
}
|
||||
Reference in New Issue
Block a user