or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-service.mdfile-service.mdfulfillment-service.mdindex.mdnotification-service.mdoauth-service.mdpayment-service.mdsearch-service.md

fulfillment-service.mddocs/

0

# Fulfillment Service

1

2

Interface for fulfillment service implementations managing shipping options, fulfillment processing, returns, and document generation for logistics operations.

3

4

**Deprecation Notice**: Use `AbstractFulfillmentService` from @medusajs/medusa instead.

5

6

## Capabilities

7

8

### Static Methods

9

10

Type checking and identification methods for fulfillment services.

11

12

```javascript { .api }

13

/**

14

* Static property identifying this as a fulfillment service

15

*/

16

static _isFulfillmentService: boolean;

17

18

/**

19

* Checks if an object is a fulfillment service

20

* @param {object} obj - Object to check

21

* @returns {boolean} True if obj is a fulfillment service

22

*/

23

static isFulfillmentService(obj: object): boolean;

24

```

25

26

### Service Identification

27

28

Method to get the service identifier.

29

30

```javascript { .api }

31

/**

32

* Returns the service identifier from constructor

33

* @returns {string} Service identifier

34

*/

35

getIdentifier(): string;

36

```

37

38

### Fulfillment Options

39

40

Methods for managing available fulfillment options and validation.

41

42

```javascript { .api }

43

/**

44

* Returns all fulfillment options that the provider can be used with

45

* Called before a shipping option is created in Admin

46

* @returns {any} Available fulfillment options

47

* @throws {Error} If not overridden by child class

48

*/

49

getFulfillmentOptions(): any;

50

51

/**

52

* Validates fulfillment option exists before creating shipping option in Admin

53

* @param {object} data - Option data to validate

54

* @returns {any} Validation result

55

* @throws {Error} If not overridden by child class

56

*/

57

validateOption(data: object): any;

58

59

/**

60

* Validates data sent with shipping method before setting on cart

61

* @param {object} optionData - The option data to validate

62

* @param {object} data - The shipping method data to validate

63

* @param {object} cart - The cart the shipping method will be applied to

64

* @returns {object} Data to populate cart.shipping_methods.$.data

65

* @throws {Error} If not overridden by child class

66

*/

67

validateFulfillmentData(optionData: object, data: object, cart?: object): object;

68

```

69

70

### Price Calculation

71

72

Methods for determining if pricing can be calculated and calculating shipping costs.

73

74

```javascript { .api }

75

/**

76

* Determines if fulfillment service can calculate price for given data

77

* @param {object} data - Data to check for price calculation capability

78

* @returns {any} True if price can be calculated

79

* @throws {Error} If not overridden by child class

80

*/

81

canCalculate(data: object): any;

82

83

/**

84

* Calculates price for a given shipping option

85

* @param {object} optionData - Shipping option data

86

* @param {object} data - Additional calculation data

87

* @param {object} cart - Cart object for calculation context

88

* @returns {any} Calculated price

89

* @throws {Error} If not overridden by child class

90

*/

91

calculatePrice(optionData: object, data: object, cart: object): any;

92

```

93

94

### Fulfillment Operations

95

96

Methods for creating and canceling fulfillments.

97

98

```javascript { .api }

99

/**

100

* Creates a fulfillment for an order

101

* @param {object} data - Fulfillment data

102

* @param {array} items - Items to fulfill

103

* @param {object} order - Order object

104

* @param {object} fulfillment - Fulfillment object

105

* @returns {any} Created fulfillment result

106

* @throws {Error} If not overridden by child class

107

*/

108

createFulfillment(data: object, items: array, order: object, fulfillment: object): any;

109

110

/**

111

* Cancels an existing fulfillment

112

* @param {object} fulfillment - Fulfillment to cancel

113

* @returns {any} Cancellation result

114

* @throws {Error} If not overridden by child class

115

*/

116

cancelFulfillment(fulfillment: object): any;

117

```

118

119

### Return Operations

120

121

Methods for handling return orders.

122

123

```javascript { .api }

124

/**

125

* Creates a return order with necessary data for future operations

126

* @param {object} fromData - Data to create return from

127

* @returns {any} Return order data

128

* @throws {Error} If not overridden by child class

129

*/

130

createReturn(fromData: object): any;

131

```

132

133

### Document Operations

134

135

Methods for retrieving documents related to fulfillments, returns, and shipments.

136

137

```javascript { .api }

138

/**

139

* Retrieves documents associated with a fulfillment

140

* @param {object} data - Fulfillment data

141

* @returns {array} Array of fulfillment documents (empty by default)

142

*/

143

getFulfillmentDocuments(data: object): array;

144

145

/**

146

* Retrieves documents related to a return order

147

* @param {object} data - Return data

148

* @returns {array} Array of return documents (empty by default)

149

*/

150

getReturnDocuments(data: object): array;

151

152

/**

153

* Retrieves documents related to a shipment

154

* @param {object} data - Shipment data

155

* @returns {array} Array of shipment documents (empty by default)

156

*/

157

getShipmentDocuments(data: object): array;

158

159

/**

160

* Retrieves documents based on fulfillment data and document type

161

* @param {object} fulfillmentData - Fulfillment data

162

* @param {string} documentType - Type of document to retrieve

163

* @returns {any} Retrieved documents

164

* @throws {Error} If not overridden by child class

165

*/

166

retrieveDocuments(fulfillmentData: object, documentType: string): any;

167

```

168

169

## Implementation Example

170

171

```javascript

172

import { FulfillmentService } from "medusa-interfaces";

173

174

class CustomFulfillmentService extends FulfillmentService {

175

static identifier = "custom-fulfillment";

176

177

constructor(options) {

178

super();

179

this.options_ = options;

180

}

181

182

getFulfillmentOptions() {

183

return [

184

{

185

id: "standard",

186

name: "Standard Shipping",

187

description: "5-7 business days"

188

},

189

{

190

id: "express",

191

name: "Express Shipping",

192

description: "1-2 business days"

193

}

194

];

195

}

196

197

validateOption(data) {

198

const validOptions = ["standard", "express"];

199

if (!validOptions.includes(data.id)) {

200

throw new Error("Invalid fulfillment option");

201

}

202

return true;

203

}

204

205

validateFulfillmentData(optionData, data, cart) {

206

// Validate shipping method data

207

if (optionData.id === "express" && !data.express_service_type) {

208

throw new Error("Express service type required");

209

}

210

211

return {

212

service_type: optionData.id,

213

validated_data: data

214

};

215

}

216

217

canCalculate(data) {

218

// Check if we have necessary data for price calculation

219

return data.destination_address && data.items;

220

}

221

222

calculatePrice(optionData, data, cart) {

223

// Calculate shipping price based on option and cart data

224

const basePrice = optionData.id === "express" ? 15.00 : 5.00;

225

const weightMultiplier = cart.items.reduce((total, item) => total + item.quantity, 0) * 0.5;

226

227

return Math.round((basePrice + weightMultiplier) * 100); // Return in cents

228

}

229

230

async createFulfillment(data, items, order, fulfillment) {

231

// Create fulfillment with external provider

232

const shipment = await this.externalProvider.createShipment({

233

items: items,

234

address: order.shipping_address,

235

service_type: data.service_type

236

});

237

238

return {

239

tracking_number: shipment.tracking_number,

240

tracking_url: shipment.tracking_url,

241

data: shipment

242

};

243

}

244

245

async cancelFulfillment(fulfillment) {

246

// Cancel fulfillment with external provider

247

await this.externalProvider.cancelShipment(fulfillment.data.id);

248

249

return {

250

status: "cancelled"

251

};

252

}

253

254

async createReturn(fromData) {

255

// Create return order

256

const returnOrder = await this.externalProvider.createReturn({

257

original_fulfillment: fromData.fulfillment_id,

258

items: fromData.items,

259

reason: fromData.reason

260

});

261

262

return {

263

return_id: returnOrder.id,

264

return_label_url: returnOrder.label_url,

265

data: returnOrder

266

};

267

}

268

269

getFulfillmentDocuments(data) {

270

return [

271

{

272

type: "shipping_label",

273

url: data.label_url

274

},

275

{

276

type: "tracking_info",

277

url: data.tracking_url

278

}

279

];

280

}

281

282

getReturnDocuments(data) {

283

return [

284

{

285

type: "return_label",

286

url: data.return_label_url

287

}

288

];

289

}

290

291

retrieveDocuments(fulfillmentData, documentType) {

292

switch (documentType) {

293

case "shipping_label":

294

return this.getFulfillmentDocuments(fulfillmentData);

295

case "return_label":

296

return this.getReturnDocuments(fulfillmentData);

297

default:

298

return [];

299

}

300

}

301

}

302

```

303

304

## Error Handling

305

306

All abstract methods throw descriptive errors when not implemented:

307

308

- `"getFulfillmentOptions must be overridden by the child class"`

309

- `"validateFulfillmentData must be overridden by the child class"`

310

- `"validateOption must be overridden by the child class"`

311

- `"canCalculate must be overridden by the child class"`

312

- `"calculatePrice must be overridden by the child class"`

313

- `"createFulfillment must be overridden by the child class"`

314

- `"cancelFulfillment must be overridden by the child class"`

315

- `"createReturn must be overridden by the child class"`

316

- `"retrieveDocuments must be overridden by the child class"`