Core interfaces for Medusa e-commerce framework service implementations
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Interface for fulfillment service implementations managing shipping options, fulfillment processing, returns, and document generation for logistics operations.
Deprecation Notice: Use AbstractFulfillmentService from @medusajs/medusa instead.
Type checking and identification methods for fulfillment services.
/**
* Static property identifying this as a fulfillment service
*/
static _isFulfillmentService: boolean;
/**
* Checks if an object is a fulfillment service
* @param {object} obj - Object to check
* @returns {boolean} True if obj is a fulfillment service
*/
static isFulfillmentService(obj: object): boolean;Method to get the service identifier.
/**
* Returns the service identifier from constructor
* @returns {string} Service identifier
*/
getIdentifier(): string;Methods for managing available fulfillment options and validation.
/**
* Returns all fulfillment options that the provider can be used with
* Called before a shipping option is created in Admin
* @returns {any} Available fulfillment options
* @throws {Error} If not overridden by child class
*/
getFulfillmentOptions(): any;
/**
* Validates fulfillment option exists before creating shipping option in Admin
* @param {object} data - Option data to validate
* @returns {any} Validation result
* @throws {Error} If not overridden by child class
*/
validateOption(data: object): any;
/**
* Validates data sent with shipping method before setting on cart
* @param {object} optionData - The option data to validate
* @param {object} data - The shipping method data to validate
* @param {object} cart - The cart the shipping method will be applied to
* @returns {object} Data to populate cart.shipping_methods.$.data
* @throws {Error} If not overridden by child class
*/
validateFulfillmentData(optionData: object, data: object, cart?: object): object;Methods for determining if pricing can be calculated and calculating shipping costs.
/**
* Determines if fulfillment service can calculate price for given data
* @param {object} data - Data to check for price calculation capability
* @returns {any} True if price can be calculated
* @throws {Error} If not overridden by child class
*/
canCalculate(data: object): any;
/**
* Calculates price for a given shipping option
* @param {object} optionData - Shipping option data
* @param {object} data - Additional calculation data
* @param {object} cart - Cart object for calculation context
* @returns {any} Calculated price
* @throws {Error} If not overridden by child class
*/
calculatePrice(optionData: object, data: object, cart: object): any;Methods for creating and canceling fulfillments.
/**
* Creates a fulfillment for an order
* @param {object} data - Fulfillment data
* @param {array} items - Items to fulfill
* @param {object} order - Order object
* @param {object} fulfillment - Fulfillment object
* @returns {any} Created fulfillment result
* @throws {Error} If not overridden by child class
*/
createFulfillment(data: object, items: array, order: object, fulfillment: object): any;
/**
* Cancels an existing fulfillment
* @param {object} fulfillment - Fulfillment to cancel
* @returns {any} Cancellation result
* @throws {Error} If not overridden by child class
*/
cancelFulfillment(fulfillment: object): any;Methods for handling return orders.
/**
* Creates a return order with necessary data for future operations
* @param {object} fromData - Data to create return from
* @returns {any} Return order data
* @throws {Error} If not overridden by child class
*/
createReturn(fromData: object): any;Methods for retrieving documents related to fulfillments, returns, and shipments.
/**
* Retrieves documents associated with a fulfillment
* @param {object} data - Fulfillment data
* @returns {array} Array of fulfillment documents (empty by default)
*/
getFulfillmentDocuments(data: object): array;
/**
* Retrieves documents related to a return order
* @param {object} data - Return data
* @returns {array} Array of return documents (empty by default)
*/
getReturnDocuments(data: object): array;
/**
* Retrieves documents related to a shipment
* @param {object} data - Shipment data
* @returns {array} Array of shipment documents (empty by default)
*/
getShipmentDocuments(data: object): array;
/**
* Retrieves documents based on fulfillment data and document type
* @param {object} fulfillmentData - Fulfillment data
* @param {string} documentType - Type of document to retrieve
* @returns {any} Retrieved documents
* @throws {Error} If not overridden by child class
*/
retrieveDocuments(fulfillmentData: object, documentType: string): any;import { FulfillmentService } from "medusa-interfaces";
class CustomFulfillmentService extends FulfillmentService {
static identifier = "custom-fulfillment";
constructor(options) {
super();
this.options_ = options;
}
getFulfillmentOptions() {
return [
{
id: "standard",
name: "Standard Shipping",
description: "5-7 business days"
},
{
id: "express",
name: "Express Shipping",
description: "1-2 business days"
}
];
}
validateOption(data) {
const validOptions = ["standard", "express"];
if (!validOptions.includes(data.id)) {
throw new Error("Invalid fulfillment option");
}
return true;
}
validateFulfillmentData(optionData, data, cart) {
// Validate shipping method data
if (optionData.id === "express" && !data.express_service_type) {
throw new Error("Express service type required");
}
return {
service_type: optionData.id,
validated_data: data
};
}
canCalculate(data) {
// Check if we have necessary data for price calculation
return data.destination_address && data.items;
}
calculatePrice(optionData, data, cart) {
// Calculate shipping price based on option and cart data
const basePrice = optionData.id === "express" ? 15.00 : 5.00;
const weightMultiplier = cart.items.reduce((total, item) => total + item.quantity, 0) * 0.5;
return Math.round((basePrice + weightMultiplier) * 100); // Return in cents
}
async createFulfillment(data, items, order, fulfillment) {
// Create fulfillment with external provider
const shipment = await this.externalProvider.createShipment({
items: items,
address: order.shipping_address,
service_type: data.service_type
});
return {
tracking_number: shipment.tracking_number,
tracking_url: shipment.tracking_url,
data: shipment
};
}
async cancelFulfillment(fulfillment) {
// Cancel fulfillment with external provider
await this.externalProvider.cancelShipment(fulfillment.data.id);
return {
status: "cancelled"
};
}
async createReturn(fromData) {
// Create return order
const returnOrder = await this.externalProvider.createReturn({
original_fulfillment: fromData.fulfillment_id,
items: fromData.items,
reason: fromData.reason
});
return {
return_id: returnOrder.id,
return_label_url: returnOrder.label_url,
data: returnOrder
};
}
getFulfillmentDocuments(data) {
return [
{
type: "shipping_label",
url: data.label_url
},
{
type: "tracking_info",
url: data.tracking_url
}
];
}
getReturnDocuments(data) {
return [
{
type: "return_label",
url: data.return_label_url
}
];
}
retrieveDocuments(fulfillmentData, documentType) {
switch (documentType) {
case "shipping_label":
return this.getFulfillmentDocuments(fulfillmentData);
case "return_label":
return this.getReturnDocuments(fulfillmentData);
default:
return [];
}
}
}All abstract methods throw descriptive errors when not implemented:
"getFulfillmentOptions must be overridden by the child class""validateFulfillmentData must be overridden by the child class""validateOption must be overridden by the child class""canCalculate must be overridden by the child class""calculatePrice must be overridden by the child class""createFulfillment must be overridden by the child class""cancelFulfillment must be overridden by the child class""createReturn must be overridden by the child class""retrieveDocuments must be overridden by the child class"