* chore: add compare_at_unit_price when price list price is retrieved
* chore: add test for update item + more fixes along the way
* chore: fix tests
* chore: add refresh spec
* Apply suggestions from code review
Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com>
* chore: use undefined checker
* chore: switch to map
---------
Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com>
**What**
- validate that variants are unique with respect to options on product update/create and variant update/create
- validate that the product has options upon creation
- ensure variants have the same number of option values as the product has options
- admin error handling
- update tests
---
FIXES FRMW-2707 CC-556
**What**
- remove cascade delete of inventory items on product delete
- implement inventory deletion in product/variant delete workflows with checks:
- product/variant cannot be deleted if there are reservations associated with their inventory items
- inventory item will be cascade deleted if it's not used by other variants (that are not being deleted in the current flow)
---
FIXES CC-581 CC-582
Fixes: FRMW-2743
This PR extracts and removes the `additional_data` from the workflow input before calling the steps and hence the `additional_data` is not passed down to the service layer.
However, this bug has made me discover one inconsistency in the input structure of certain workflows.
✅ **Following is the input structure of the `updateProductsWorkflow`**. Here, we accept the `products` and the `additional_data` as two separate top-level properties.
```ts
// Shape
export type UpdateProductsWorkflowInputSelector = {
selector: ProductTypes.FilterableProductProps
update: Omit<ProductTypes.UpdateProductDTO, "variants"> & {
sales_channels?: { id: string }[]
variants?: UpdateProductVariantWorkflowInputDTO[]
}
} & AdditionalData
// Calling the workflow
const { result } = await updateProductsWorkflow(req.scope).run({
input: {
selector: { id: req.params.id },
update,
additional_data,
},
})
```
❌ **Following in the input structure of the `updateCartWorflow`**. In this case, we are accepting the cart properties at the top-level, hence the `additional_data` is merged within those properties, increasing the chance of passing it down to the service layer by mistake.
```ts
// Shape
WorkflowData<UpdateCartWorkflowInputDTO & AdditionalData>
// Calling the workflow
await workflow.run({
input: {
...req.validatedBody // Additional data is part of the validatedBody,
id: req.params.id,
},
})
```
Ideally, the input of `updateCartWorkflow` should look as follows.
```ts
WorkflowData<{ cart: UpdateCartWorkflowInputDTO } & AdditionalData>
```
**What**
- fix `prepareConfirmInventory` to account for inventory kit items
- _note: this step is reused in the complete cart and all RMA flows_
- properly remove reservations for items that are removed from the order edit
- invalidate inventory/reservations cache when order edit is confirmed
---
https://github.com/user-attachments/assets/f12e9198-0718-4c08-bd81-efc536eca146
---
FIXES CC-565
What
- Store result of cart-completion workflow for three days by default
- This enables the built-in idempotency mechanism to kick-in, provided the same transaction ID is used on workflow executions
- Return order from cart-completion workflow if the cart has already been completed
- In case transaction ID is not used on workflow executions, we still only want to complete a cart once
**What**
If the country on the shipping address changes to a country without an associated tax region, we clear the tax lines on shipping methods and line items.
**What**
On cart creation:
- If region only has one country -> create cart with country code
On cart updates:
- If shipping address country code is provided in input ->
- If cart region doesn't include that country -> throw
- If cart includes the country -> update shipping address
- If region is provided in input and is different from the one currently on the cart ->
- If there is a shipping address on the cart -> clear the address
- If the region only has one country -> set country code of address
- If there is not a shipping address on the cart ->
- If the region only has one country -> set country code of address
Closes CC-545
**What**
The `updateTaxLinesWorkflow` rely on the cart shipping method meaning that concurrent refresh of shipping method can impact tax lines therefore leading to wrong tax lines
**What**
- Removes broken cart retrieval step `retrieveWithCartLinks` in favor of `useRemoteQueryStep` in `updateTaxLinesWorkflows`
**Why**
- Filters variables in the step were passed with an incorrect shape
- I removed the step, since it's only used once and the behavior is identical to the generic remote query step
**Note**
- Because the filters were passed incorrectly, the, now-removed, step has always returned the first cart in the database. As a result all tax calculations so far have been based on whatever the shape of that cart has. It basically ignores all input to this workflow
**What**
- Adds a step to `updateShippingOptionsWorkflow` and `createShippingOptionsWorkflow` that validates if the region prices being updated have corresponding regions configured.
**Why**
- Previously, if you tried to send a region price update for a region that had been deleted the backend would throw an error when attempting to insert the region price. The error comes from a not-null constraint in the db, but it is better to validate that the regions we are trying to create prices for exist.
Fixes CC-542
**What**
- Fetches the stock location's details when creating a fulfillment and return fulfillment.
- Passes the data to the fulfillment module, which in turn passes it to the fulfillment provider.
**Why**
- When creating a fulfillment in a multi-location setup the fulfillment provider will need to know where the package is being sent from (so the shipping service can pick it up).
- Previously, we didn't pass anything but the location id to the fulfillment provider. Because the fulfillment provider can't have a dependency on the stock location module this was not sufficient.
- This change ensures there is enough data passed to the fulfillment provider to build integrations properly.
what:
- when an empty array is passed to the workflow, it attempts to delete all inventory locations. This PR adds a conditional to prevent it from happening.
RESOLVES CC-477
Fixes https://github.com/medusajs/medusa/issues/9154
**What**
- on cart completion, when creating reservations, use line item id instead of cart item id
- NOTE: inventory reservation is now done after we create the order
---
FIXES CC-448