feat(core-flows, dashboard, fulfillment, fulfillment-manual, utils, types): create shipping options with calculated prices (#10495)

**What**
- support creating SO with calculated price
- support updating SO for both types of pricing
- update `validateShippingOptionPricesStep` to handle both SO price_types
- add the `validateShippingOptionsForPriceCalculation` method to `FulfillementModule`
- add `canCalculate` and `calculatePrice` to fulfillment provider service service / interface / manual provider
- disable SO pricing edit on Admin if SO price type is calculated

---

CLOSES CMRC-776
This commit is contained in:
Frane Polić
2024-12-11 09:38:44 +01:00
committed by GitHub
parent fad85a9d29
commit d8a92dbb2d
13 changed files with 253 additions and 53 deletions

View File

@@ -1970,6 +1970,34 @@ export default class FulfillmentModuleService
return !!shippingOptions.length
}
@InjectManager()
async validateShippingOptionsForPriceCalculation(
shippingOptionsData: FulfillmentTypes.CreateShippingOptionDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<boolean[]> {
const nonCalculatedOptions = shippingOptionsData.filter(
(option) => option.price_type !== "calculated"
)
if (nonCalculatedOptions.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Cannot calculate price for non-calculated shipping options: ${nonCalculatedOptions
.map((o) => o.name)
.join(", ")}`
)
}
const promises = shippingOptionsData.map((option) =>
this.fulfillmentProviderService_.canCalculate(
option.provider_id,
option as unknown as Record<string, unknown>
)
)
return await promiseAll(promises)
}
@InjectTransactionManager()
// @ts-expect-error
async deleteShippingProfiles(

View File

@@ -100,6 +100,21 @@ export default class FulfillmentProviderService extends ModulesSdkUtils.MedusaIn
return await provider.validateOption(data)
}
async canCalculate(providerId: string, data: Record<string, unknown>) {
const provider = this.retrieveProviderRegistration(providerId)
return await provider.canCalculate(data)
}
async calculatePrice(
providerId: string,
optionData: Record<string, unknown>,
data: Record<string, unknown>,
context: Record<string, unknown>
) {
const provider = this.retrieveProviderRegistration(providerId)
return await provider.calculatePrice(optionData, data, context)
}
async createFulfillment(
providerId: string,
data: object,

View File

@@ -1,5 +1,8 @@
import { AbstractFulfillmentProviderService } from "@medusajs/framework/utils"
import { FulfillmentOption } from "@medusajs/types"
import {
CalculatedShippingOptionPrice,
FulfillmentOption,
} from "@medusajs/types"
// TODO rework type and DTO's
@@ -30,6 +33,18 @@ export class ManualFulfillmentService extends AbstractFulfillmentProviderService
return data
}
async calculatePrice(
optionData: Record<string, unknown>,
data: Record<string, unknown>,
context: Record<string, unknown>
): Promise<CalculatedShippingOptionPrice> {
throw new Error("Manual fulfillment does not support price calculation")
}
async canCalculate(): Promise<boolean> {
return false
}
async validateOption(data: Record<string, any>): Promise<boolean> {
return true
}