CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-medusa-interfaces

Core interfaces for Medusa e-commerce framework service implementations

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

fulfillment-service.mddocs/

Fulfillment Service

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.

Capabilities

Static Methods

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;

Service Identification

Method to get the service identifier.

/**
 * Returns the service identifier from constructor
 * @returns {string} Service identifier
 */
getIdentifier(): string;

Fulfillment Options

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;

Price Calculation

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;

Fulfillment Operations

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;

Return Operations

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;

Document Operations

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;

Implementation Example

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 [];
    }
  }
}

Error Handling

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"

docs

base-service.md

file-service.md

fulfillment-service.md

index.md

notification-service.md

oauth-service.md

payment-service.md

search-service.md

tile.json