fix(stock-location,core-flows,types): updates existing address when updating stock location (#10832)

* fix(stock-location,core-flows,types): updates existing address when updating stock location address

* chore: use hasOne instead of hasMany
This commit is contained in:
Riqwan Thamir authored and GitHub committed 2025-01-07 07:55:28 +01:00
1 parent fde73dbfae
commit 99a06102a2
10 files changed
+336 -7

No files matched your search

@@ -0,0 +1,73 @@
import {
IStockLocationService,
UpsertStockLocationAddressInput,
} from "@medusajs/framework/types"
import {
getSelectsAndRelationsFromObjectArray,
promiseAll,
} from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
import { Modules } from "@medusajs/framework/utils"
export const upsertStockLocationAddressesStepId =
"upsert-stock-location-addresses-step"
/**
* This step upserts stock location addresses matching the specified filters.
*/
export const upsertStockLocationAddressesStep = createStep(
upsertStockLocationAddressesStepId,
async (input: UpsertStockLocationAddressInput[], { container }) => {
const stockLocationService = container.resolve<IStockLocationService>(
Modules.STOCK_LOCATION
)
const stockLocationAddressIds = input.map((i) => i.id!).filter(Boolean)
const { selects, relations } = getSelectsAndRelationsFromObjectArray(input)
const dataToUpdate = await stockLocationService.listStockLocationAddresses(
{ id: stockLocationAddressIds },
{ select: selects, relations }
)
const updateIds = dataToUpdate.map((du) => du.id)
const updatedAddresses =
await stockLocationService.upsertStockLocationAddresses(input)
const dataToDelete = updatedAddresses.filter(
(address) => !updateIds.includes(address.id)
)
return new StepResponse(updatedAddresses, { dataToUpdate, dataToDelete })
},
async (revertData, { container }) => {
if (!revertData) {
return
}
const stockLocationService = container.resolve<IStockLocationService>(
Modules.STOCK_LOCATION
)
const promises: any[] = []
if (revertData.dataToDelete) {
promises.push(
stockLocationService.deleteStockLocationAddresses(
revertData.dataToDelete.map((d) => d.id!)
)
)
}
if (revertData.dataToUpdate) {
promises.push(
stockLocationService.upsertStockLocationAddresses(
revertData.dataToUpdate
)
)
}
await promiseAll(promises)
}
)
@@ -1,15 +1,19 @@
import {
FilterableStockLocationProps,
StockLocationDTO,
UpdateStockLocationInput,
FilterableStockLocationProps,
UpsertStockLocationAddressInput,
} from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
createWorkflow,
transform,
} from "@medusajs/framework/workflows-sdk"
import { useQueryGraphStep } from "../../common"
import { updateStockLocationsStep } from "../steps"
import { upsertStockLocationAddressesStep } from "../steps/upsert-stock-location-addresses"
export interface UpdateStockLocationsWorkflowInput {
selector: FilterableStockLocationProps
@@ -24,6 +28,50 @@ export const updateStockLocationsWorkflow = createWorkflow(
(
input: WorkflowData<UpdateStockLocationsWorkflowInput>
): WorkflowResponse<StockLocationDTO[]> => {
return new WorkflowResponse(updateStockLocationsStep(input))
const stockLocationsQuery = useQueryGraphStep({
entity: "stock_location",
filters: input.selector,
fields: ["id", "address.id"],
}).config({ name: "get-stock-location" })
const stockLocations = transform(
{ stockLocationsQuery },
({ stockLocationsQuery }) => stockLocationsQuery.data
)
const normalizedData = transform(
{ input, stockLocations },
({ input, stockLocations }) => {
const { address, address_id, ...stockLocationInput } = input.update
const addressesInput: UpsertStockLocationAddressInput[] = []
if (address) {
for (const stockLocation of stockLocations) {
if (stockLocation.address?.id) {
addressesInput.push({
id: stockLocation.address?.id!,
...address,
})
} else {
addressesInput.push(address)
}
}
}
return {
stockLocationInput: {
selector: input.selector,
update: stockLocationInput,
},
addressesInput,
}
}
)
upsertStockLocationAddressesStep(normalizedData.addressesInput)
return new WorkflowResponse(
updateStockLocationsStep(normalizedData.stockLocationInput)
)
}
)
@@ -452,3 +452,19 @@ export type UpsertStockLocationInput = Partial<UpdateStockLocationInput> & {
*/
id?: string
}
export type UpdateStockLocationAddressInput = StockLocationAddressInput & {
id: string
}
export type UpsertStockLocationAddressInput = StockLocationAddressInput & {
id?: string
}
export interface FilterableStockLocationAddressProps
extends BaseFilterable<FilterableStockLocationAddressProps> {
/**
* The IDs to filter stock location's address by.
*/
id?: string | string[]
}
@@ -1,14 +1,17 @@
import { FindConfig } from "../common/common"
import { RestoreReturn, SoftDeleteReturn } from "../dal"
import { IModuleService } from "../modules-sdk"
import { Context } from "../shared-context"
import {
CreateStockLocationInput,
FilterableStockLocationAddressProps,
FilterableStockLocationProps,
StockLocationAddressDTO,
StockLocationDTO,
UpdateStockLocationInput,
UpsertStockLocationAddressInput,
UpsertStockLocationInput,
} from "./common"
import { RestoreReturn, SoftDeleteReturn } from "../dal"
import { Context } from "../shared-context"
import { FindConfig } from "../common/common"
import { IModuleService } from "../modules-sdk"
/**
* The main service interface for the Stock Location Module.
@@ -333,4 +336,50 @@ export interface IStockLocationService extends IModuleService {
config?: RestoreReturn<TReturnableLinkableKeys>,
sharedContext?: Context
): Promise<Record<string, string[]> | void>
/**
* This method retrieves a paginated list of stock location addresses based on optional filters and configuration.
*
* @param {FilterableStockLocationAddressProps} selector - The filters to apply on the retrieved stock location address.
* @param {FindConfig<StockLocationAddressDTO>} config - The configurations determining how the stock location address is retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a stock location address.
* @param {Context} context - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<StockLocationAddressDTO[]>} The list of stock location addressess.
*
*/
listStockLocationAddresses(
selector: FilterableStockLocationAddressProps,
config?: FindConfig<StockLocationAddressDTO>,
context?: Context
): Promise<StockLocationAddressDTO[]>
/**
* This method updates or creates stock location addresses
*
* @param {Partial<UpsertStockLocationAddressInput>[]} data - The list of Make all properties in t optional
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<StockLocationAddressDTO[]>} The created or updated stock location address
*
* @example
* {example-code}
*/
upsertStockLocationAddresses(
data: UpsertStockLocationAddressInput[],
sharedContext?: Context
): Promise<StockLocationAddressDTO[]>
/**
* This method deletes a stock location address by its ID.
*
* @param {string} id - The ID of the stock location address.
* @param {Context} context - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves when the stock location address is deleted successfully.
*
* @example
* await stockLocationModuleService.deleteStockLocationAddresses("sla_123")
*/
deleteStockLocationAddresses(
id: string | string[],
context?: Context
): Promise<void>
}