fix(core-flows): Locations levels check in draft order and order edit flows (#12881)

* fix: Inventory check

* mend

* centralise fields

* Create few-owls-push.md
This commit is contained in:
Oli Juhl
2025-07-03 17:31:04 +02:00
committed by GitHub
parent 779ed018b9
commit 46bf7ae7ae
12 changed files with 233 additions and 93 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/core-flows": patch
---
fix(core-flows): Locations levels check in draft order and order edit flows

View File

@@ -25,6 +25,7 @@ medusaIntegrationTestRunner({
let inventoryItem
let inventoryItemExtra
let location
let locationTwo
let productExtra
const shippingProviderId = "manual_test-provider"
@@ -553,10 +554,29 @@ medusaIntegrationTestRunner({
)
).data.stock_location
locationTwo = (
await api.post(
`/admin/stock-locations`,
{
name: "Test location two",
},
adminHeaders
)
).data.stock_location
await api.post(
`/admin/inventory-items/${inventoryItemLarge.id}/location-levels`,
{
location_id: location.id,
stocked_quantity: 0,
},
adminHeaders
)
await api.post(
`/admin/inventory-items/${inventoryItemLarge.id}/location-levels`,
{
location_id: locationTwo.id,
stocked_quantity: 10,
},
adminHeaders
@@ -766,6 +786,14 @@ medusaIntegrationTestRunner({
stock_location_id: location.id,
},
},
{
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannel.id,
},
[Modules.STOCK_LOCATION]: {
stock_location_id: locationTwo.id,
},
},
])
})
@@ -860,6 +888,60 @@ medusaIntegrationTestRunner({
])
)
})
it("should manage inventory across locations in order edit", async () => {
let edit = (
await api.post(
`/admin/order-edits`,
{ order_id: order.id },
adminHeaders
)
).data.order_change
// Add item
await api.post(
`/admin/order-edits/${order.id}/items`,
{
items: [
{
variant_id: product.variants.find((v) => v.title === "L shirt")
.id,
quantity: 1,
},
],
},
adminHeaders
)
edit = (
await api.post(
`/admin/order-edits/${order.id}/request`,
{},
adminHeaders
)
).data.order_change
edit = (
await api.post(
`/admin/order-edits/${order.id}/confirm`,
{},
adminHeaders
)
).data.order_change
order = (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data
.order
expect(order.items.length).toBe(3)
expect(order.items).toEqual(
expect.arrayContaining([
expect.objectContaining({
subtitle: "L shirt",
quantity: 2,
}),
])
)
})
})
describe("Order Edit Shipping Methods", () => {

View File

@@ -118,6 +118,7 @@ export const completeCartFields = [
"items.variant.inventory_items.inventory.location_levels.reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.location_id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.name",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
@@ -168,6 +169,7 @@ export const productVariantsFields = [
"inventory_items.inventory.requires_shipping",
"inventory_items.inventory.location_levels.stocked_quantity",
"inventory_items.inventory.location_levels.reserved_quantity",
"inventory_items.inventory.location_levels.location_id",
"inventory_items.inventory.location_levels.raw_stocked_quantity",
"inventory_items.inventory.location_levels.raw_reserved_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",

View File

@@ -9,6 +9,43 @@ import {
deepFlatMap,
} from "@medusajs/framework/utils"
export const requiredOrderFieldsForInventoryConfirmation = [
"id",
"version",
"canceled_at",
"sales_channel_id",
"items.*",
"items.variant.manage_inventory",
"items.variant.allow_backorder",
"items.variant.inventory_items.inventory_item_id",
"items.variant.inventory_items.required_quantity",
"items.variant.inventory_items.inventory.location_levels.stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_stocked_quantity",
"items.variant.inventory_items.inventory.location_levels.raw_reserved_quantity",
"items.variant.inventory_items.inventory.location_levels.location_id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.name",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
]
export const requiredVariantFieldsForInventoryConfirmation = [
"manage_inventory",
"allow_backorder",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.location_levels.stocked_quantity",
"inventory_items.inventory.location_levels.reserved_quantity",
"inventory_items.inventory.location_levels.raw_stocked_quantity",
"inventory_items.inventory.location_levels.raw_reserved_quantity",
"inventory_items.inventory.location_levels.location_id",
"inventory_items.inventory.location_levels.stock_locations.id",
"inventory_items.inventory.location_levels.stock_locations.name",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
]
interface ConfirmInventoryPreparationInput {
product_variant_inventory_items: {
variant_id: string

View File

@@ -3,7 +3,11 @@ import {
AddToCartWorkflowInputDTO,
ConfirmVariantInventoryWorkflowInputDTO,
} from "@medusajs/framework/types"
import { CartWorkflowEvents, isDefined } from "@medusajs/framework/utils"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
} from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
@@ -28,13 +32,14 @@ import {
cartFieldsForPricingContext,
productVariantsFields,
} from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshCartItemsWorkflow } from "./refresh-cart-items"
import { pricingContextResult } from "../utils/schemas"
const cartFields = ["completed_at"].concat(cartFieldsForPricingContext)
@@ -71,9 +76,9 @@ export const addToCartWorkflowId = "add-to-cart"
*
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.setPricingContext - This hook is executed after the cart is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the cart.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
@@ -81,13 +86,13 @@ export const addToCartWorkflowId = "add-to-cart"
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { addToCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* addToCartWorkflow.hooks.setPricingContext((
* { cart, variantIds, items, additional_data }, { container }
* ) => {
@@ -96,13 +101,13 @@ export const addToCartWorkflowId = "add-to-cart"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const addToCartWorkflow = createWorkflow(
@@ -163,7 +168,10 @@ export const addToCartWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {

View File

@@ -4,6 +4,7 @@ import {
} from "@medusajs/framework/types"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
MedusaError,
} from "@medusajs/framework/utils"
@@ -25,18 +26,19 @@ import {
findSalesChannelStep,
} from "../steps"
import { validateLineItemPricesStep } from "../steps/validate-line-item-prices"
import { validateSalesChannelStep } from "../steps/validate-sales-channel"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import { productVariantsFields } from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
import { updateTaxLinesWorkflow } from "./update-tax-lines"
import { validateSalesChannelStep } from "../steps/validate-sales-channel"
import { pricingContextResult } from "../utils/schemas"
/**
* The data to create the cart, along with custom data that's passed to the workflow's hooks.
@@ -78,9 +80,9 @@ export const createCartWorkflowId = "create-cart"
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.cartCreated - This hook is executed after a cart is created. You can consume this hook to perform custom actions on the created cart.
* @property hooks.setPricingContext - This hook is executed after the cart is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the cart.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
@@ -88,13 +90,13 @@ export const createCartWorkflowId = "create-cart"
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { createCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* createCartWorkflow.hooks.setPricingContext((
* { region, variantIds, salesChannel, customerData, additional_data }, { container }
* ) => {
@@ -103,13 +105,13 @@ export const createCartWorkflowId = "create-cart"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const createCartWorkflow = createWorkflow(
@@ -170,7 +172,10 @@ export const createCartWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {

View File

@@ -2,7 +2,12 @@ import {
AdditionalData,
UpdateLineItemInCartWorkflowInputDTO,
} from "@medusajs/framework/types"
import { CartWorkflowEvents, isDefined, MedusaError } from "@medusajs/framework/utils"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
MedusaError,
} from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
@@ -21,9 +26,10 @@ import {
cartFieldsForPricingContext,
productVariantsFields,
} from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { refreshCartItemsWorkflow } from "./refresh-cart-items"
import { pricingContextResult } from "../utils/schemas"
const cartFields = cartFieldsForPricingContext.concat(["items.*"])
@@ -52,9 +58,9 @@ export const updateLineItemInCartWorkflowId = "update-line-item-in-cart"
*
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.setPricingContext - This hook is executed before the cart is updated. You can consume this hook to return any custom context useful for the prices retrieval of the line item's variant.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
@@ -62,13 +68,13 @@ export const updateLineItemInCartWorkflowId = "update-line-item-in-cart"
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { addToCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* addToCartWorkflow.hooks.setPricingContext((
* { cart, variantIds, items, additional_data }, { container }
* ) => {
@@ -77,13 +83,13 @@ export const updateLineItemInCartWorkflowId = "update-line-item-in-cart"
* });
* });
* ```
*
*
* The variant's prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const updateLineItemInCartWorkflow = createWorkflow(
@@ -148,7 +154,10 @@ export const updateLineItemInCartWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {

View File

@@ -10,7 +10,10 @@ import {
} from "@medusajs/framework/workflows-sdk"
import { BigNumberInput, OrderChangeDTO, OrderDTO } from "@medusajs/types"
import { reserveInventoryStep } from "../../cart"
import { prepareConfirmInventoryInput } from "../../cart/utils/prepare-confirm-inventory-input"
import {
prepareConfirmInventoryInput,
requiredOrderFieldsForInventoryConfirmation,
} from "../../cart/utils/prepare-confirm-inventory-input"
import { useRemoteQueryStep } from "../../common"
import {
createOrUpdateOrderPaymentCollectionWorkflow,
@@ -114,21 +117,7 @@ export const confirmDraftOrderEditWorkflow = createWorkflow(
const orderItems = useRemoteQueryStep({
entry_point: "order",
fields: [
"id",
"version",
"canceled_at",
"sales_channel_id",
"items.*",
"items.variant.manage_inventory",
"items.variant.allow_backorder",
"items.variant.inventory_items.inventory_item_id",
"items.variant.inventory_items.required_quantity",
"items.variant.inventory_items.inventory.location_levels.stock_locations.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.name",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
],
fields: requiredOrderFieldsForInventoryConfirmation,
variables: { id: input.order_id },
list: false,
throw_if_key_not_found: true,

View File

@@ -19,6 +19,7 @@ export const productVariantsFields = [
"inventory_items.inventory.requires_shipping",
"inventory_items.inventory.location_levels.stocked_quantity",
"inventory_items.inventory.location_levels.reserved_quantity",
"inventory_items.inventory.location_levels.location_id",
"inventory_items.inventory.location_levels.raw_stocked_quantity",
"inventory_items.inventory.location_levels.raw_reserved_quantity",
"inventory_items.inventory.location_levels.stock_locations.id",

View File

@@ -3,7 +3,7 @@ import {
OrderLineItemDTO,
OrderWorkflow,
} from "@medusajs/framework/types"
import { isDefined, MedusaError } from "@medusajs/framework/utils"
import { deduplicate, isDefined, MedusaError } from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
@@ -18,15 +18,16 @@ import { findOrCreateCustomerStep } from "../../cart/steps/find-or-create-custom
import { findSalesChannelStep } from "../../cart/steps/find-sales-channel"
import { validateLineItemPricesStep } from "../../cart/steps/validate-line-item-prices"
import { validateVariantPricesStep } from "../../cart/steps/validate-variant-prices"
import { requiredVariantFieldsForInventoryConfirmation } from "../../cart/utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../../cart/utils/prepare-line-item-data"
import { pricingContextResult } from "../../cart/utils/schemas"
import { confirmVariantInventoryWorkflow } from "../../cart/workflows/confirm-variant-inventory"
import { useRemoteQueryStep } from "../../common"
import { createOrderLineItemsStep } from "../steps"
import { productVariantsFields } from "../utils/fields"
import { pricingContextResult } from "../../cart/utils/schemas"
function prepareLineItems(data) {
const items = (data.input.items ?? []).map((item) => {
@@ -84,11 +85,11 @@ export const addOrderLineItemsWorkflowId = "order-add-line-items"
* @summary
*
* Add line items to an order.
*
*
* @property hooks.setPricingContext - This hook is executed after the order is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the order.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
@@ -96,13 +97,13 @@ export const addOrderLineItemsWorkflowId = "order-add-line-items"
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { addOrderLineItemsWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* addOrderLineItemsWorkflow.hooks.setPricingContext((
* { order, variantIds, region, customerData, additional_data }, { container }
* ) => {
@@ -111,13 +112,13 @@ export const addOrderLineItemsWorkflowId = "order-add-line-items"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const addOrderLineItemsWorkflow = createWorkflow(
@@ -197,7 +198,10 @@ export const addOrderLineItemsWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {

View File

@@ -1,5 +1,10 @@
import { AdditionalData, CreateOrderDTO } from "@medusajs/framework/types"
import { MedusaError, isDefined, isPresent } from "@medusajs/framework/utils"
import {
MedusaError,
deduplicate,
isDefined,
isPresent,
} from "@medusajs/framework/utils"
import {
WorkflowData,
WorkflowResponse,
@@ -14,16 +19,17 @@ import { findOrCreateCustomerStep } from "../../cart/steps/find-or-create-custom
import { findSalesChannelStep } from "../../cart/steps/find-sales-channel"
import { validateLineItemPricesStep } from "../../cart/steps/validate-line-item-prices"
import { validateVariantPricesStep } from "../../cart/steps/validate-variant-prices"
import { requiredVariantFieldsForInventoryConfirmation } from "../../cart/utils/prepare-confirm-inventory-input"
import {
PrepareLineItemDataInput,
prepareLineItemData,
} from "../../cart/utils/prepare-line-item-data"
import { pricingContextResult } from "../../cart/utils/schemas"
import { confirmVariantInventoryWorkflow } from "../../cart/workflows/confirm-variant-inventory"
import { useRemoteQueryStep } from "../../common"
import { createOrdersStep } from "../steps"
import { productVariantsFields } from "../utils/fields"
import { updateOrderTaxLinesWorkflow } from "./update-tax-lines"
import { pricingContextResult } from "../../cart/utils/schemas"
function prepareLineItems(data) {
const items = (data.input.items ?? []).map((item) => {
@@ -129,9 +135,9 @@ export const createOrdersWorkflowId = "create-orders"
*
* @property hooks.orderCreated - This hook is executed after the order is created. You can consume this hook to perform custom actions on the created order.
* @property hooks.setPricingContext - This hook is executed after the order is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the order.
*
*
* For example, assuming you have the following custom pricing rule:
*
*
* ```json
* {
* "attribute": "location_id",
@@ -139,13 +145,13 @@ export const createOrdersWorkflowId = "create-orders"
* "value": "sloc_123",
* }
* ```
*
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
*
* ```ts
* import { createOrderWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
*
* createOrderWorkflow.hooks.setPricingContext((
* { variantIds, region, customerData, additional_data }, { container }
* ) => {
@@ -154,13 +160,13 @@ export const createOrdersWorkflowId = "create-orders"
* });
* });
* ```
*
*
* The variants' prices will now be retrieved using the context you return.
*
*
* :::note
*
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
*
* :::
*/
export const createOrderWorkflow = createWorkflow(
@@ -221,7 +227,10 @@ export const createOrderWorkflow = createWorkflow(
}).then(() => {
return useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
variables: {
id: variantIds,
calculated_price: {

View File

@@ -17,7 +17,10 @@ import {
transform,
} from "@medusajs/framework/workflows-sdk"
import { reserveInventoryStep } from "../../../cart/steps/reserve-inventory"
import { prepareConfirmInventoryInput } from "../../../cart/utils/prepare-confirm-inventory-input"
import {
prepareConfirmInventoryInput,
requiredOrderFieldsForInventoryConfirmation,
} from "../../../cart/utils/prepare-confirm-inventory-input"
import { emitEventStep, useRemoteQueryStep } from "../../../common"
import { deleteReservationsByLineItemsStep } from "../../../reservation"
import { previewOrderChangeStep } from "../../steps"
@@ -171,21 +174,7 @@ export const confirmOrderEditRequestWorkflow = createWorkflow(
const orderItems = useRemoteQueryStep({
entry_point: "order",
fields: [
"id",
"version",
"canceled_at",
"sales_channel_id",
"items.*",
"items.variant.manage_inventory",
"items.variant.allow_backorder",
"items.variant.inventory_items.inventory_item_id",
"items.variant.inventory_items.required_quantity",
"items.variant.inventory_items.inventory.location_levels.stock_locations.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.name",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
"items.variant.inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
],
fields: requiredOrderFieldsForInventoryConfirmation,
variables: { id: input.order_id },
list: false,
throw_if_key_not_found: true,