medusa-shiprocket-fulfillment-plugin 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/vite-env.d.js +1 -0
- package/.medusa/server/src/admin/widgets/printables.js +82 -0
- package/.medusa/server/src/api/admin/plugin/route.js +7 -0
- package/.medusa/server/src/api/store/plugin/route.js +7 -0
- package/.medusa/server/src/jobs/refresh-shiprocket-token.js +32 -0
- package/.medusa/server/src/providers/shiprocket/client/handle-error.js +27 -0
- package/.medusa/server/src/providers/shiprocket/client/index.js +311 -0
- package/.medusa/server/src/providers/shiprocket/client/methods/authenticate.js +38 -0
- package/.medusa/server/src/providers/shiprocket/client/types/index.js +3 -0
- package/.medusa/server/src/providers/shiprocket/index.js +11 -0
- package/.medusa/server/src/providers/shiprocket/service.js +206 -0
- package/.medusa/server/src/providers/shiprocket/types/index.js +3 -0
- package/.medusa/server/src/providers/shiprocket/utils/index.js +25 -0
- package/README.md +236 -0
- package/package.json +78 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { defineWidgetConfig } from "@medusajs/admin-sdk";
|
|
3
|
+
import { Container, Heading, Text } from "@medusajs/ui";
|
|
4
|
+
const ShiprocketTrackingWidget = ({ data: order }) => {
|
|
5
|
+
var _a;
|
|
6
|
+
if (!(order == null ? void 0 : order.id) || !(order == null ? void 0 : order.fulfillments)) return null;
|
|
7
|
+
const activeShipments = (_a = order.fulfillments) == null ? void 0 : _a.filter(
|
|
8
|
+
(f) => {
|
|
9
|
+
var _a2;
|
|
10
|
+
return !f.canceled_at && f.data.awb && f.data.shipment_id && ((_a2 = f.provider) == null ? void 0 : _a2.id) === "shiprocket_shiprocket";
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
return /* @__PURE__ */ jsxs(Container, { className: "p-6 rounded-lg shadow-lg border border-neutral-700", children: [
|
|
14
|
+
/* @__PURE__ */ jsx("header", { className: "mb-6", children: /* @__PURE__ */ jsx(Heading, { level: "h2", className: "font-semibold text-lg text-white", children: "Shiprocket Printables" }) }),
|
|
15
|
+
(activeShipments == null ? void 0 : activeShipments.length) === 0 ? /* @__PURE__ */ jsx(Text, { className: "text-sm italic text-gray-400", children: "No active shipments" }) : /* @__PURE__ */ jsx("ul", { className: "space-y-6", children: activeShipments.map((fulfillment) => {
|
|
16
|
+
var _a2, _b, _c, _d, _e, _f, _g;
|
|
17
|
+
return /* @__PURE__ */ jsxs(
|
|
18
|
+
"li",
|
|
19
|
+
{
|
|
20
|
+
className: "bg-neutral-900/10 rounded-xl shadow-none p-5 flex flex-col gap-4 border border-neutral-900/10",
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
|
|
23
|
+
/* @__PURE__ */ jsxs(Text, { className: "text-sm text-gray-300 font-normal", children: [
|
|
24
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-normal text-white", children: "Shipment ID:" }),
|
|
25
|
+
" ",
|
|
26
|
+
((_a2 = fulfillment.data) == null ? void 0 : _a2.shipment_id) || "No AWB found"
|
|
27
|
+
] }),
|
|
28
|
+
/* @__PURE__ */ jsx("span", { className: `
|
|
29
|
+
px-2 py-1 rounded-lg shadow-none text-[9px] font-semibold uppercase select-none
|
|
30
|
+
${fulfillment.status === "delivered" ? "bg-green-500 text-black" : fulfillment.status === "pending" ? "bg-yellow-400 text-black" : "bg-red-700 text-white"}
|
|
31
|
+
min-w-[4.5rem] text-center`, children: fulfillment.status || "Cancelled" })
|
|
32
|
+
] }),
|
|
33
|
+
JSON.stringify(fulfillment, null, 2),
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-center items-center gap-3 mt-4", children: [
|
|
35
|
+
((_b = fulfillment.labels) == null ? void 0 : _b.label_url) && /* @__PURE__ */ jsx(
|
|
36
|
+
"a",
|
|
37
|
+
{
|
|
38
|
+
href: `${(_c = fulfillment.labels) == null ? void 0 : _c.label_url}`,
|
|
39
|
+
target: "_blank",
|
|
40
|
+
rel: "noopener noreferrer",
|
|
41
|
+
className: "flex-1 px-4 py-1 text-xs bg-neutral-900/60 font-medium hover:bg-neutral-900/90 rounded-lg transition-colors text-center",
|
|
42
|
+
"aria-disabled": "false",
|
|
43
|
+
children: "Label"
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
((_d = fulfillment.labels) == null ? void 0 : _d.manifest_url) && /* @__PURE__ */ jsx(
|
|
47
|
+
"a",
|
|
48
|
+
{
|
|
49
|
+
href: `${(_e = fulfillment.labels) == null ? void 0 : _e.manifest_url}`,
|
|
50
|
+
target: "_blank",
|
|
51
|
+
rel: "noopener noreferrer",
|
|
52
|
+
className: "flex-1 px-4 py-1 text-xs bg-neutral-900/60 font-medium hover:bg-neutral-900/90 rounded-lg transition-colors text-center",
|
|
53
|
+
"aria-disabled": "false",
|
|
54
|
+
children: "Manifest"
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
((_f = fulfillment.labels) == null ? void 0 : _f.invoice_url) && /* @__PURE__ */ jsx(
|
|
58
|
+
"a",
|
|
59
|
+
{
|
|
60
|
+
href: `${(_g = fulfillment.labels) == null ? void 0 : _g.invoice_url}`,
|
|
61
|
+
target: "_blank",
|
|
62
|
+
rel: "noopener noreferrer",
|
|
63
|
+
className: "flex-1 px-4 py-1 text-xs bg-neutral-900/60 font-medium hover:bg-neutral-900/90 rounded-lg transition-colors text-center",
|
|
64
|
+
"aria-disabled": "false",
|
|
65
|
+
children: "Invoice"
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
] })
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
fulfillment.id
|
|
72
|
+
);
|
|
73
|
+
}) })
|
|
74
|
+
] });
|
|
75
|
+
};
|
|
76
|
+
const config = defineWidgetConfig({
|
|
77
|
+
zone: "order.details.side.after"
|
|
78
|
+
});
|
|
79
|
+
export {
|
|
80
|
+
config,
|
|
81
|
+
ShiprocketTrackingWidget as default
|
|
82
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = GET;
|
|
4
|
+
async function GET(req, res) {
|
|
5
|
+
res.sendStatus(200);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = GET;
|
|
4
|
+
async function GET(req, res) {
|
|
5
|
+
res.sendStatus(200);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.config = void 0;
|
|
7
|
+
exports.default = refreshShiprocketTokenJob;
|
|
8
|
+
const client_1 = __importDefault(require("../providers/shiprocket/client"));
|
|
9
|
+
async function refreshShiprocketTokenJob(container) {
|
|
10
|
+
const options = {
|
|
11
|
+
email: process.env.SHIPROCKET_EMAIL,
|
|
12
|
+
password: process.env.SHIPROCKET_PASSWORD,
|
|
13
|
+
};
|
|
14
|
+
const client = new client_1.default(options);
|
|
15
|
+
try {
|
|
16
|
+
await client["ensureAuthenticated"]?.();
|
|
17
|
+
// Optionally, log or store the refreshed token somewhere if needed
|
|
18
|
+
container.resolve("logger").info("Shiprocket token refreshed");
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
// Optionally, log error
|
|
22
|
+
container.resolve("logger").error("Failed to refresh Shiprocket token", err);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
client.dispose();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.config = {
|
|
29
|
+
name: "refresh-shiprocket-token",
|
|
30
|
+
schedule: "0 0 */8 * *", // every 8 days at 00:00
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmcmVzaC1zaGlwcm9ja2V0LXRva2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2pvYnMvcmVmcmVzaC1zaGlwcm9ja2V0LXRva2VuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUlBLDRDQWdCQztBQWxCRCw0RUFBNkQ7QUFFOUMsS0FBSyxVQUFVLHlCQUF5QixDQUFDLFNBQTBCO0lBQzlFLE1BQU0sT0FBTyxHQUE0QjtRQUNyQyxLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBaUI7UUFDcEMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW9CO0tBQzdDLENBQUE7SUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQzVDLElBQUksQ0FBQztRQUNELE1BQU0sTUFBTSxDQUFDLHFCQUFxQixDQUFDLEVBQUUsRUFBRSxDQUFBO1FBQ3ZDLG1FQUFtRTtRQUNuRSxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFBO0lBQ2xFLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ1gsd0JBQXdCO1FBQ3hCLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxFQUFFLEdBQUcsQ0FBQyxDQUFBO0lBQ2hGLENBQUM7WUFBUyxDQUFDO1FBQ1AsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ3BCLENBQUM7QUFDTCxDQUFDO0FBRVksUUFBQSxNQUFNLEdBQUc7SUFDbEIsSUFBSSxFQUFFLDBCQUEwQjtJQUNoQyxRQUFRLEVBQUUsYUFBYSxFQUFFLHdCQUF3QjtDQUNwRCxDQUFBIn0=
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleError = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/utils");
|
|
5
|
+
const handleError = (error) => {
|
|
6
|
+
const message = error.response?.data?.message || error.message;
|
|
7
|
+
const code = error.response?.status || 500;
|
|
8
|
+
if (code === 401) {
|
|
9
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Authentication failed with Shiprocket");
|
|
10
|
+
}
|
|
11
|
+
if (code === 429) {
|
|
12
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Rate limit exceeded. Please try again later.");
|
|
13
|
+
}
|
|
14
|
+
if (code === 400 && error.response?.data?.errors) {
|
|
15
|
+
const validationErrors = Object.entries(error.response.data.errors)
|
|
16
|
+
.map(([field, msgs]) => `${field}: ${Array.isArray(msgs) ? msgs.join(", ") : msgs}`)
|
|
17
|
+
.join("; ");
|
|
18
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Validation failed: ${validationErrors}`);
|
|
19
|
+
}
|
|
20
|
+
throw new utils_1.MedusaError(code === 404
|
|
21
|
+
? utils_1.MedusaError.Types.NOT_FOUND
|
|
22
|
+
: code === 400
|
|
23
|
+
? utils_1.MedusaError.Types.INVALID_DATA
|
|
24
|
+
: utils_1.MedusaError.Types.UNEXPECTED_STATE, message);
|
|
25
|
+
};
|
|
26
|
+
exports.handleError = handleError;
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlLWVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9zaGlwcm9ja2V0L2NsaWVudC9oYW5kbGUtZXJyb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQTZDO0FBR3RDLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBa0MsRUFBUyxFQUFFO0lBQ3JFLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE9BQU8sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFBO0lBQzlELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxJQUFJLEdBQUcsQ0FBQTtJQUUxQyxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNmLE1BQU0sSUFBSSxtQkFBVyxDQUNqQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHVDQUF1QyxDQUMxQyxDQUFBO0lBQ0wsQ0FBQztJQUVELElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2YsTUFBTSxJQUFJLG1CQUFXLENBQ2pCLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsOENBQThDLENBQ2pELENBQUE7SUFDTCxDQUFDO0lBRUQsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQy9DLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7YUFDOUQsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQ25GLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNmLE1BQU0sSUFBSSxtQkFBVyxDQUNqQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHNCQUFzQixnQkFBZ0IsRUFBRSxDQUMzQyxDQUFBO0lBQ0wsQ0FBQztJQUVELE1BQU0sSUFBSSxtQkFBVyxDQUNqQixJQUFJLEtBQUssR0FBRztRQUNSLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxTQUFTO1FBQzdCLENBQUMsQ0FBQyxJQUFJLEtBQUssR0FBRztZQUNkLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZO1lBQ2hDLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDeEMsT0FBTyxDQUNWLENBQUE7QUFDTCxDQUFDLENBQUE7QUFwQ1ksUUFBQSxXQUFXLGVBb0N2QiJ9
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const axios_1 = __importDefault(require("axios"));
|
|
7
|
+
const utils_1 = require("@medusajs/utils");
|
|
8
|
+
const authenticate_1 = require("./methods/authenticate");
|
|
9
|
+
const handle_error_1 = require("./handle-error");
|
|
10
|
+
class ShiprocketClient {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.token = null;
|
|
13
|
+
this.tokenExpiry = null;
|
|
14
|
+
this.refreshTimeout = null;
|
|
15
|
+
this.isDisposed = false;
|
|
16
|
+
if (!options.email || !options.password) {
|
|
17
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Shiprocket API credentials are required");
|
|
18
|
+
}
|
|
19
|
+
this.email = options.email;
|
|
20
|
+
this.password = options.password;
|
|
21
|
+
this.pickup_location = options.pickup_location;
|
|
22
|
+
this.axios = axios_1.default.create({
|
|
23
|
+
baseURL: "https://apiv2.shiprocket.in/v1/external",
|
|
24
|
+
headers: { "Content-Type": "application/json" },
|
|
25
|
+
timeout: 10000,
|
|
26
|
+
});
|
|
27
|
+
process.on("beforeExit", () => this.dispose());
|
|
28
|
+
}
|
|
29
|
+
dispose() {
|
|
30
|
+
if (this.isDisposed)
|
|
31
|
+
return;
|
|
32
|
+
if (this.refreshTimeout) {
|
|
33
|
+
clearTimeout(this.refreshTimeout);
|
|
34
|
+
this.refreshTimeout = null;
|
|
35
|
+
}
|
|
36
|
+
this.token = null;
|
|
37
|
+
this.tokenExpiry = null;
|
|
38
|
+
this.isDisposed = true;
|
|
39
|
+
}
|
|
40
|
+
async ensureAuthenticated() {
|
|
41
|
+
if (!this.token || !this.tokenExpiry || Date.now() > this.tokenExpiry) {
|
|
42
|
+
const auth = await (0, authenticate_1.authenticate)(this.axios, this.email, this.password, this.isDisposed);
|
|
43
|
+
this.token = auth.token;
|
|
44
|
+
this.tokenExpiry = auth.tokenExpiry;
|
|
45
|
+
this.axios.defaults.headers.common["Authorization"] = `Bearer ${this.token}`;
|
|
46
|
+
if (this.refreshTimeout)
|
|
47
|
+
clearTimeout(this.refreshTimeout);
|
|
48
|
+
this.refreshTimeout = setTimeout(() => {
|
|
49
|
+
this.ensureAuthenticated().catch((error) => {
|
|
50
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to refresh Shiprocket token: ${error.message}`);
|
|
51
|
+
});
|
|
52
|
+
}, 8 * 24 * 60 * 60 * 1000 // Refresh after 8 days
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async calculate(data) {
|
|
57
|
+
await this.ensureAuthenticated();
|
|
58
|
+
try {
|
|
59
|
+
const response = await this.axios.get("/courier/serviceability/", { params: data });
|
|
60
|
+
const availableCouriers = response.data.data.available_courier_companies;
|
|
61
|
+
if (!availableCouriers?.length) {
|
|
62
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, "No couriers available for this route");
|
|
63
|
+
}
|
|
64
|
+
const filtered = data.allowed_courier_ids?.length
|
|
65
|
+
? availableCouriers.filter((c) => data.allowed_courier_ids.includes(c.id))
|
|
66
|
+
: availableCouriers;
|
|
67
|
+
if (!filtered?.length) {
|
|
68
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, "No allowed couriers available for this route");
|
|
69
|
+
}
|
|
70
|
+
const cheapest = filtered.reduce((min, curr) => Number(curr.rate) < Number(min.rate) ? curr : min);
|
|
71
|
+
return Math.ceil(Number(cheapest?.rate) || 0);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
(0, handle_error_1.handleError)(error);
|
|
75
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Rate calculation failed unexpectedly");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async create(fulfillment, items, order) {
|
|
79
|
+
await this.ensureAuthenticated();
|
|
80
|
+
const safe = (v, fallback) => (v != null ? v : fallback);
|
|
81
|
+
const orderItemMap = new Map();
|
|
82
|
+
if (Array.isArray(order.items)) {
|
|
83
|
+
order.items.forEach((orderItem) => {
|
|
84
|
+
orderItemMap.set(orderItem.id, orderItem);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
let totalWeight = 0;
|
|
88
|
+
let totalLength = 0;
|
|
89
|
+
let totalBreadth = 0;
|
|
90
|
+
let totalHeight = 0;
|
|
91
|
+
try {
|
|
92
|
+
const order_date = new Date(order.created_at)
|
|
93
|
+
.toLocaleString("en-GB", {
|
|
94
|
+
day: "2-digit",
|
|
95
|
+
month: "2-digit",
|
|
96
|
+
year: "numeric",
|
|
97
|
+
hour: "2-digit",
|
|
98
|
+
minute: "2-digit",
|
|
99
|
+
hour12: false,
|
|
100
|
+
})
|
|
101
|
+
.replace(",", "")
|
|
102
|
+
.replace(/\//g, "-");
|
|
103
|
+
const totalCost = items.reduce((sum, fi) => {
|
|
104
|
+
const orderItem = orderItemMap.get(fi.line_item_id);
|
|
105
|
+
if (!orderItem) {
|
|
106
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Fulfillment item ${fi.id} (${fi.title}) has no matching order item with line_item_id: ${fi.line_item_id}`);
|
|
107
|
+
}
|
|
108
|
+
const unit = Number(orderItem.unit_price ?? orderItem.detail?.unit_price ?? 0);
|
|
109
|
+
const qty = Number(fi.quantity ?? fi.raw_quantity?.value ?? 0);
|
|
110
|
+
if (!unit || !qty) {
|
|
111
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Missing unit price or quantity for fulfillment item: ${JSON.stringify(fi)}`);
|
|
112
|
+
}
|
|
113
|
+
return sum + unit * qty;
|
|
114
|
+
}, 0);
|
|
115
|
+
const shipping = order.shipping_address || fulfillment?.delivery_address || {};
|
|
116
|
+
const billing = order.customer || {};
|
|
117
|
+
const region = order.region || {};
|
|
118
|
+
items.forEach((item) => {
|
|
119
|
+
const orderItem = orderItemMap.get(item.line_item_id);
|
|
120
|
+
if (!orderItem) {
|
|
121
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Order item not found for fulfillment item: ${item.title} (line_item_id: ${item.line_item_id})`);
|
|
122
|
+
}
|
|
123
|
+
const variant = orderItem.variant;
|
|
124
|
+
if (!variant) {
|
|
125
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Variant data not found for order item: ${orderItem.id}`);
|
|
126
|
+
}
|
|
127
|
+
const weight = Number(variant.weight || 0) / 1000;
|
|
128
|
+
const length = Number(variant.length || 0);
|
|
129
|
+
const breadth = Number(variant.width || 0);
|
|
130
|
+
const height = Number(variant.height || 0);
|
|
131
|
+
if (!weight || !length || !breadth || !height) {
|
|
132
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Missing dimensions/weight for item "${item.title}" (Order Item: ${orderItem.id}, Variant: ${variant.id}).
|
|
133
|
+
Please set weight, length, width, and height in the product variant settings in Medusa Admin.`);
|
|
134
|
+
}
|
|
135
|
+
const quantity = Number(item.quantity || item.raw_quantity?.value || 1);
|
|
136
|
+
totalWeight += weight * quantity;
|
|
137
|
+
totalLength = Math.max(totalLength, length);
|
|
138
|
+
totalBreadth = Math.max(totalBreadth, breadth);
|
|
139
|
+
totalHeight += height * quantity;
|
|
140
|
+
});
|
|
141
|
+
const orderData = {
|
|
142
|
+
order_id: order.id + "-" + Math.random().toString().slice(2, 12),
|
|
143
|
+
order_date,
|
|
144
|
+
pickup_location: this.pickup_location || "Primary",
|
|
145
|
+
billing_customer_name: safe(billing.first_name, ""),
|
|
146
|
+
billing_last_name: safe(billing.last_name, ""),
|
|
147
|
+
billing_address: safe(shipping.address_1, ""),
|
|
148
|
+
billing_address_2: safe(shipping.address_2, ""),
|
|
149
|
+
billing_city: safe(shipping.city, ""),
|
|
150
|
+
billing_pincode: Number(safe(shipping.postal_code, "110001")),
|
|
151
|
+
billing_state: safe(shipping.province, ""),
|
|
152
|
+
billing_country: safe(region.name, "India"),
|
|
153
|
+
billing_email: safe(billing.email, ""),
|
|
154
|
+
billing_phone: Number(safe(shipping.phone, "9999999999").toString().replace(/[^0-9]/g, "")),
|
|
155
|
+
shipping_is_billing: true,
|
|
156
|
+
shipping_customer_name: safe(shipping.first_name, ""),
|
|
157
|
+
shipping_last_name: safe(shipping.last_name, ""),
|
|
158
|
+
shipping_address: safe(shipping.address_1, ""),
|
|
159
|
+
shipping_address_2: safe(shipping.address_2, ""),
|
|
160
|
+
shipping_city: safe(shipping.city, ""),
|
|
161
|
+
shipping_pincode: Number(safe(shipping.postal_code, "110001")),
|
|
162
|
+
shipping_country: safe(region.name, "India"),
|
|
163
|
+
shipping_state: safe(shipping.province, ""),
|
|
164
|
+
shipping_email: safe(billing.email, ""),
|
|
165
|
+
shipping_phone: Number(safe(shipping.phone, "9999999999").toString().replace(/[^0-9]/g, "")),
|
|
166
|
+
order_items: items.map((item) => {
|
|
167
|
+
const orderItem = orderItemMap.get(item.line_item_id);
|
|
168
|
+
const variant = orderItem.variant;
|
|
169
|
+
const selling_price = Math.round(Number(orderItem.unit_price || orderItem.detail?.unit_price || 0));
|
|
170
|
+
const hsn_code = variant.hs_code ? Number(variant.hs_code) : 0;
|
|
171
|
+
return {
|
|
172
|
+
name: item.title,
|
|
173
|
+
sku: variant.sku || orderItem.variant_sku || item.sku || item.id,
|
|
174
|
+
units: Number(item.quantity || item.raw_quantity?.value || 1),
|
|
175
|
+
selling_price,
|
|
176
|
+
discount: "",
|
|
177
|
+
tax: "",
|
|
178
|
+
hsn: hsn_code,
|
|
179
|
+
};
|
|
180
|
+
}),
|
|
181
|
+
payment_method: "Prepaid",
|
|
182
|
+
shipping_charges: 0,
|
|
183
|
+
giftwrap_charges: 0,
|
|
184
|
+
transaction_charges: 0,
|
|
185
|
+
total_discount: Number(order.discount_total || 0),
|
|
186
|
+
sub_total: totalCost,
|
|
187
|
+
length: totalLength,
|
|
188
|
+
breadth: totalBreadth,
|
|
189
|
+
height: totalHeight,
|
|
190
|
+
weight: totalWeight,
|
|
191
|
+
};
|
|
192
|
+
const orderCreated = await this.axios
|
|
193
|
+
.post("/orders/create/adhoc", orderData)
|
|
194
|
+
.catch((err) => {
|
|
195
|
+
const apiError = err;
|
|
196
|
+
const firstError = apiError.response?.data?.errors
|
|
197
|
+
? Object.values(apiError.response.data.errors)[0][0]
|
|
198
|
+
: "Unknown error";
|
|
199
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, firstError);
|
|
200
|
+
});
|
|
201
|
+
if (!orderCreated.data?.shipment_id) {
|
|
202
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Failed to create Shiprocket order");
|
|
203
|
+
}
|
|
204
|
+
const awbCreated = await this.axios.post(`/courier/assign/awb`, {
|
|
205
|
+
shipment_id: orderCreated.data.shipment_id,
|
|
206
|
+
courier_id: orderCreated.data.courier_company_id,
|
|
207
|
+
});
|
|
208
|
+
if (awbCreated.data.awb_assign_status !== 1) {
|
|
209
|
+
try {
|
|
210
|
+
await this.cancel(orderCreated.data.order_id);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
// swallow cancel error but log upstream if needed
|
|
214
|
+
}
|
|
215
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, awbCreated.data.message || "AWB assignment failed");
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
order_id: orderCreated.data.order_id,
|
|
219
|
+
shipment_id: orderCreated.data.shipment_id,
|
|
220
|
+
status: orderCreated.data.status,
|
|
221
|
+
status_code: orderCreated.data.status_code,
|
|
222
|
+
awb: awbCreated.data.response.data.awb_code,
|
|
223
|
+
courier_company_id: awbCreated.data.response.data.courier_company_id,
|
|
224
|
+
courier_name: orderCreated.data.courier_name,
|
|
225
|
+
tracking_number: awbCreated.data.response.data.awb_code,
|
|
226
|
+
tracking_url: "https://shiprocket.co/tracking/" + awbCreated.data.response.data.awb_code,
|
|
227
|
+
label_url: orderCreated.data.label_url,
|
|
228
|
+
shipping_charges: orderCreated.data.shipping_charges,
|
|
229
|
+
payment_method: orderCreated.data.payment_method,
|
|
230
|
+
transaction_charges: orderCreated.data.transaction_charges,
|
|
231
|
+
giftwrap_charges: orderCreated.data.giftwrap_charges,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
(0, handle_error_1.handleError)(error);
|
|
236
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Order creation failed unexpectedly");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async cancel(orderId) {
|
|
240
|
+
await this.ensureAuthenticated();
|
|
241
|
+
try {
|
|
242
|
+
await this.axios.post(`/orders/cancel`, { ids: [orderId] });
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
(0, handle_error_1.handleError)(error);
|
|
246
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, error.message || "Order cancellation failed unexpectedly");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async getTrackingInfo(trackingNumber) {
|
|
250
|
+
await this.ensureAuthenticated();
|
|
251
|
+
try {
|
|
252
|
+
const response = await this.axios.get(`/courier/track/awb/${trackingNumber}`);
|
|
253
|
+
return response.data;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
(0, handle_error_1.handleError)(error);
|
|
257
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Tracking info retrieval failed unexpectedly");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async createReturn(fulfillment) {
|
|
261
|
+
await this.ensureAuthenticated();
|
|
262
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Not Implemented. Please create a return order manually.");
|
|
263
|
+
return {
|
|
264
|
+
order_id: fulfillment.external_id,
|
|
265
|
+
shipment_id: fulfillment.external_id,
|
|
266
|
+
status: "success",
|
|
267
|
+
status_code: 200,
|
|
268
|
+
awb: "1234567890",
|
|
269
|
+
courier_company_id: 1,
|
|
270
|
+
courier_name: "DHL",
|
|
271
|
+
tracking_number: "1234567890",
|
|
272
|
+
tracking_url: "",
|
|
273
|
+
label_url: "",
|
|
274
|
+
payment_method: "cod",
|
|
275
|
+
shipping_charges: "0",
|
|
276
|
+
transaction_charges: "0",
|
|
277
|
+
giftwrap_charges: "0",
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
async createDocuments(fulfillment) {
|
|
281
|
+
await this.ensureAuthenticated();
|
|
282
|
+
const manifest = await this.axios.get(`/manifests/generate`, {
|
|
283
|
+
params: { order_ids: [fulfillment.shipment_id] },
|
|
284
|
+
});
|
|
285
|
+
const label = await this.axios.get(`/courier/generate/label`, {
|
|
286
|
+
params: { shipment_id: [fulfillment.shipment_id] },
|
|
287
|
+
});
|
|
288
|
+
const invoice = await this.axios.get(`/orders/print/invoice`, {
|
|
289
|
+
params: { ids: [fulfillment.order_id] },
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
label: label[0].label_created === 1 ? label[0].label_url : "",
|
|
293
|
+
manifest: manifest[0].status === 1 ? manifest[0].manifest_url : "",
|
|
294
|
+
invoice: invoice[0].is_invoice_created ? invoice[0].invoice_url : "",
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
async generateLabel(fulfillment) {
|
|
298
|
+
const label = await this.axios.get(`/courier/generate/label`, {
|
|
299
|
+
params: { shipment_id: [fulfillment.shipment_id] },
|
|
300
|
+
});
|
|
301
|
+
return label[0].label_url;
|
|
302
|
+
}
|
|
303
|
+
async generateInvoice(fulfillment) {
|
|
304
|
+
const invoice = await this.axios.get(`/orders/print/invoice`, {
|
|
305
|
+
params: { ids: [fulfillment.order_id] },
|
|
306
|
+
});
|
|
307
|
+
return invoice[0].invoice_url;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
exports.default = ShiprocketClient;
|
|
311
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3NoaXByb2NrZXQvY2xpZW50L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTRDO0FBQzVDLDJDQUE2QztBQUM3Qyx5REFBcUQ7QUFDckQsaURBQTRDO0FBVTVDLE1BQU0sZ0JBQWdCO0lBVWxCLFlBQVksT0FBZ0M7UUFMcEMsVUFBSyxHQUFrQixJQUFJLENBQUE7UUFDM0IsZ0JBQVcsR0FBa0IsSUFBSSxDQUFBO1FBQ2pDLG1CQUFjLEdBQTBCLElBQUksQ0FBQTtRQUM1QyxlQUFVLEdBQUcsS0FBSyxDQUFBO1FBR3RCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxtQkFBVyxDQUNqQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHlDQUF5QyxDQUM1QyxDQUFBO1FBQ0wsQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQTtRQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUE7UUFDaEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFBO1FBQzlDLElBQUksQ0FBQyxLQUFLLEdBQUcsZUFBSyxDQUFDLE1BQU0sQ0FBQztZQUN0QixPQUFPLEVBQUUseUNBQXlDO1lBQ2xELE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRTtZQUMvQyxPQUFPLEVBQUUsS0FBSztTQUNqQixDQUFDLENBQUE7UUFDRixPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNsRCxDQUFDO0lBRUQsT0FBTztRQUNILElBQUksSUFBSSxD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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticate = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/utils");
|
|
5
|
+
const handle_error_1 = require("../handle-error");
|
|
6
|
+
/**
|
|
7
|
+
* Authenticates with the Shiprocket API to get a token.
|
|
8
|
+
* @param axios - The Axios instance to use for the request.
|
|
9
|
+
* @param email - The user's email.
|
|
10
|
+
* @param password - The user's password.
|
|
11
|
+
* @param isDisposed - Whether the client is disposed.
|
|
12
|
+
* @returns The authentication token and its expiry time.
|
|
13
|
+
*/
|
|
14
|
+
const authenticate = async (axios, email, password, isDisposed) => {
|
|
15
|
+
if (isDisposed) {
|
|
16
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Cannot authenticate disposed client");
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const response = await axios.post("/auth/login", {
|
|
20
|
+
email,
|
|
21
|
+
password,
|
|
22
|
+
});
|
|
23
|
+
if (!response.data.token) {
|
|
24
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "No token received in authentication response");
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
token: response.data.token,
|
|
28
|
+
// Token valid for 10 days, refresh after 8
|
|
29
|
+
tokenExpiry: Date.now() + 8 * 24 * 60 * 60 * 1000,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
(0, handle_error_1.handleError)(error);
|
|
34
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Authentication failed unexpectedly");
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.authenticate = authenticate;
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aGVudGljYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9zaGlwcm9ja2V0L2NsaWVudC9tZXRob2RzL2F1dGhlbnRpY2F0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBNkM7QUFFN0Msa0RBQTZDO0FBRzdDOzs7Ozs7O0dBT0c7QUFDSSxNQUFNLFlBQVksR0FBRyxLQUFLLEVBQzdCLEtBQW9CLEVBQ3BCLEtBQWEsRUFDYixRQUFnQixFQUNoQixVQUFtQixFQUM0QixFQUFFO0lBQ2pELElBQUksVUFBVSxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksbUJBQVcsQ0FDakIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQ2xDLHFDQUFxQyxDQUN4QyxDQUFBO0lBQ0wsQ0FBQztJQUVELElBQUksQ0FBQztRQUNELE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBeUIsYUFBYSxFQUFFO1lBQ3JFLEtBQUs7WUFDTCxRQUFRO1NBQ1gsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLG1CQUFXLENBQ2pCLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsOENBQThDLENBQ2pELENBQUE7UUFDTCxDQUFDO1FBRUQsT0FBTztZQUNILEtBQUssRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUs7WUFDMUIsMkNBQTJDO1lBQzNDLFdBQVcsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUk7U0FDcEQsQ0FBQTtJQUNMLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsSUFBQSwwQkFBVyxFQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2xCLE1BQU0sSUFBSSxtQkFBVyxDQUNqQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDbEMsb0NBQW9DLENBQ3ZDLENBQUE7SUFDTCxDQUFDO0FBQ0wsQ0FBQyxDQUFBO0FBdENZLFFBQUEsWUFBWSxnQkFzQ3hCIn0=
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3NoaXByb2NrZXQvY2xpZW50L3R5cGVzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const service_1 = __importDefault(require("./service"));
|
|
8
|
+
exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.FULFILLMENT, {
|
|
9
|
+
services: [service_1.default],
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3NoaXByb2NrZXQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBbUU7QUFDbkUsd0RBQTREO0FBRTVELGtCQUFlLElBQUEsc0JBQWMsRUFBQyxlQUFPLENBQUMsV0FBVyxFQUFFO0lBQy9DLFFBQVEsRUFBRSxDQUFDLGlCQUFvQyxDQUFDO0NBQ25ELENBQUMsQ0FBQSJ9
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const client_1 = __importDefault(require("./client"));
|
|
8
|
+
class ShipRocketFulfillmentProviderService extends utils_1.AbstractFulfillmentProviderService {
|
|
9
|
+
/**
|
|
10
|
+
* Constructs a new instance of the ShipRocketFulfillmentProviderService.
|
|
11
|
+
* @param {Logger} logger - The logger instance.
|
|
12
|
+
* @param {Options} options - The options for the Shiprocket client.
|
|
13
|
+
*/
|
|
14
|
+
constructor({ logger }, options) {
|
|
15
|
+
super();
|
|
16
|
+
this.logger_ = logger;
|
|
17
|
+
this.options_ = options;
|
|
18
|
+
this.client = new client_1.default({
|
|
19
|
+
email: options.email,
|
|
20
|
+
password: options.password,
|
|
21
|
+
pickup_location: options.pickup_location,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the fulfillment options for Shiprocket.
|
|
26
|
+
* @returns An array of fulfillment options.
|
|
27
|
+
*/
|
|
28
|
+
async getFulfillmentOptions() {
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
id: "Standard Shipping",
|
|
32
|
+
name: "Standard Shipping",
|
|
33
|
+
is_return: false,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "Return Shipping",
|
|
37
|
+
name: "Return Shipping",
|
|
38
|
+
is_return: true,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Determines whether the fulfillment option can calculate the shipping rate.
|
|
44
|
+
* @param data - The fulfillment option data.
|
|
45
|
+
* @returns A promise that resolves to a boolean indicating whether the option can calculate the rate.
|
|
46
|
+
*/
|
|
47
|
+
async canCalculate(data) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Calculates the shipping rate for a given order.
|
|
52
|
+
* @param optionData - The fulfillment option data.
|
|
53
|
+
* @param data - The fulfillment data.
|
|
54
|
+
* @param context - The fulfillment context.
|
|
55
|
+
* @returns The calculated shipping rate.
|
|
56
|
+
* @throws {Error} If either pickup or delivery postcodes are missing.
|
|
57
|
+
* @throws {Error} If weight is missing.
|
|
58
|
+
*/
|
|
59
|
+
async calculatePrice(optionData, data, context) {
|
|
60
|
+
const params = {
|
|
61
|
+
pickup_postcode: context["from_location"]?.address?.postal_code,
|
|
62
|
+
delivery_postcode: context["shipping_address"]?.postal_code,
|
|
63
|
+
weight: (context["items"]?.[0]?.metadata?.weight),
|
|
64
|
+
cod: (this.options_.cod !== "true") ? 0 : 1,
|
|
65
|
+
};
|
|
66
|
+
if (!params.pickup_postcode || !params.delivery_postcode) {
|
|
67
|
+
throw new Error("Both pickup and delivery postcodes are required for rate calculation.");
|
|
68
|
+
}
|
|
69
|
+
if (!params.weight) {
|
|
70
|
+
throw new Error("Weight is required for rate calculation.");
|
|
71
|
+
}
|
|
72
|
+
const price = await this.client.calculate(params);
|
|
73
|
+
return {
|
|
74
|
+
calculated_amount: price,
|
|
75
|
+
is_calculated_price_tax_inclusive: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates a fulfillment in Shiprocket.
|
|
80
|
+
* @param data - The fulfillment data.
|
|
81
|
+
* @param items - The items in the fulfillment.
|
|
82
|
+
* @param order - The order associated with the fulfillment.
|
|
83
|
+
* @param fulfillment - The fulfillment data.
|
|
84
|
+
* @returns The created fulfillment data.
|
|
85
|
+
*/
|
|
86
|
+
async createFulfillment(data, items, order, fulfillment) {
|
|
87
|
+
try {
|
|
88
|
+
const externalData = await this.client.create(fulfillment, items, order);
|
|
89
|
+
const { label, manifest, invoice } = await this.client.createDocuments(externalData);
|
|
90
|
+
return {
|
|
91
|
+
data: {
|
|
92
|
+
...(fulfillment || {}),
|
|
93
|
+
...externalData,
|
|
94
|
+
},
|
|
95
|
+
labels: [
|
|
96
|
+
{
|
|
97
|
+
tracking_number: externalData.tracking_number || "",
|
|
98
|
+
tracking_url: externalData.tracking_url || "",
|
|
99
|
+
label_url: label || "",
|
|
100
|
+
invoice_url: invoice || "",
|
|
101
|
+
manifest_url: manifest || "",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, (err?.message || err?.response?.data?.message || "Failed to create fulfillment"));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Cancels a fulfillment in Shiprocket.
|
|
112
|
+
* @param data - The fulfillment data.
|
|
113
|
+
* @throws {MedusaError} If the order ID is not provided.
|
|
114
|
+
*/
|
|
115
|
+
async cancelFulfillment(data) {
|
|
116
|
+
const { order_id } = data;
|
|
117
|
+
if (!order_id) {
|
|
118
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Order ID is required");
|
|
119
|
+
}
|
|
120
|
+
await this.client.cancel(order_id);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Creates a return fulfillment in Shiprocket.
|
|
124
|
+
* @param fulfillment - The fulfillment data.
|
|
125
|
+
* @returns The created return fulfillment data.
|
|
126
|
+
*/
|
|
127
|
+
async createReturnFulfillment(fulfillment) {
|
|
128
|
+
const externalData = await this.client.createReturn(fulfillment);
|
|
129
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Not Implemented. Please create a return order manually.");
|
|
130
|
+
return {
|
|
131
|
+
data: {
|
|
132
|
+
...(fulfillment || {}),
|
|
133
|
+
...externalData,
|
|
134
|
+
},
|
|
135
|
+
labels: [
|
|
136
|
+
{
|
|
137
|
+
tracking_number: externalData.tracking_number || "",
|
|
138
|
+
tracking_url: externalData.tracking_url || "",
|
|
139
|
+
label_url: externalData.label_url || "",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Retrieves the documents associated with a fulfillment.
|
|
146
|
+
* @param data - The fulfillment data.
|
|
147
|
+
* @returns An array of documents associated with the fulfillment.
|
|
148
|
+
*/
|
|
149
|
+
async getFulfillmentDocuments(data) {
|
|
150
|
+
const invoice = await this.client.generateInvoice(data);
|
|
151
|
+
return invoice || [];
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Retrieves the documents associated with a shipment.
|
|
155
|
+
* @param data - The shipment data.
|
|
156
|
+
* @returns An array of documents associated with the shipment.
|
|
157
|
+
*/
|
|
158
|
+
async getShipmentDocuments(data) {
|
|
159
|
+
const label = await this.client.generateLabel(data);
|
|
160
|
+
return label || [];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Retrieves the documents associated with a return fulfillment.
|
|
164
|
+
* @param data - The return fulfillment data.
|
|
165
|
+
* @returns An empty array, as document retrieval is not supported for returns.
|
|
166
|
+
*/
|
|
167
|
+
async getReturnDocuments(data) {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Retrieves the documents associated with a fulfillment, given its data and the type of documents to retrieve.
|
|
172
|
+
* @param fulfillmentData - The fulfillment data.
|
|
173
|
+
* @param documentType - The type of documents to retrieve.
|
|
174
|
+
* @returns A promise that resolves once the documents have been retrieved.
|
|
175
|
+
* @remarks Document retrieval is not supported by this provider.
|
|
176
|
+
*/
|
|
177
|
+
async retrieveDocuments(fulfillmentData, documentType) {
|
|
178
|
+
this.logger_.debug("Document retrieval not supported");
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Validates the fulfillment data to ensure it has the required information.
|
|
182
|
+
* If the external ID is not present, it will be generated automatically.
|
|
183
|
+
* @param optionData - The data provided by the user when creating a fulfillment option.
|
|
184
|
+
* @param data - The data provided by the user when creating a fulfillment.
|
|
185
|
+
* @param context - The context of the fulfillment.
|
|
186
|
+
* @returns A promise that resolves with the validated fulfillment data.
|
|
187
|
+
*/
|
|
188
|
+
async validateFulfillmentData(optionData, data, context) {
|
|
189
|
+
return {
|
|
190
|
+
...data,
|
|
191
|
+
external_id: `temp_${Date.now()}`,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Validates a fulfillment option to ensure it has the required information.
|
|
196
|
+
* @param data - The data provided by the user when creating a fulfillment option.
|
|
197
|
+
* @returns A promise that resolves with a boolean indicating whether the option is valid.
|
|
198
|
+
* @remarks A fulfillment option is valid if it has an external ID.
|
|
199
|
+
*/
|
|
200
|
+
async validateOption(data) {
|
|
201
|
+
return data.external_id !== undefined;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
ShipRocketFulfillmentProviderService.identifier = "shiprocket";
|
|
205
|
+
exports.default = ShipRocketFulfillmentProviderService;
|
|
206
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvc2hpcHJvY2tldC9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscURBQTRGO0FBYTVGLHNEQUF3QztBQWF4QyxNQUFNLG9DQUFxQyxTQUFRLDBDQUFrQztJQU9qRjs7OztPQUlHO0lBQ0gsWUFBWSxFQUFFLE1BQU0sRUFBd0IsRUFBRSxPQUFnQjtRQUMxRCxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQztZQUMvQixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7WUFDcEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLGVBQWUsRUFBRSxPQUFPLENBQUMsZUFBZTtTQUMzQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLHFCQUFxQjtRQUN2QixPQUFPO1lBQ0g7Z0JBQ0ksRUFBRSxFQUFFLG1CQUFtQjtnQkFDdkIsSUFBSSxFQUFFLG1CQUFtQjtnQkFDekIsU0FBUyxFQUFFLEtBQUs7YUFDbkI7WUFDRDtnQkFDSSxFQUFFLEVBQUUsaUJBQWlCO2dCQUNyQixJQUFJLEVBQUUsaUJBQWlCO2dCQUN2QixTQUFTLEVBQUUsSUFBSTthQUNsQjtTQUNKLENBQUM7SUFDTixDQUFDO0lBR0Q7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBNkI7UUFDNUMsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUNEOzs7Ozs7OztPQVFHO0lBRUgsS0FBSyxDQUFDLGNBQWMsQ0FDaEIsVUFBeUQsRUFDekQsSUFBNkMsRUFDN0MsT0FBbUQ7UUFFbkQsTUFBTSxNQUFNLEdBQUc7WUFD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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3NoaXByb2NrZXQvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCheapestCourier = getCheapestCourier;
|
|
4
|
+
exports.filterAllowedCouriers = filterAllowedCouriers;
|
|
5
|
+
exports.slugify = slugify;
|
|
6
|
+
function getCheapestCourier(couriers) {
|
|
7
|
+
const validCouriers = couriers.filter((c) => !!c.rate && !isNaN(Number(c.rate)));
|
|
8
|
+
if (validCouriers.length === 0)
|
|
9
|
+
return null;
|
|
10
|
+
return validCouriers.reduce((min, curr) => {
|
|
11
|
+
return Number(curr.rate) < Number(min.rate) ? curr : min;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function filterAllowedCouriers(couriers, allowedCourierIds) {
|
|
15
|
+
return couriers.filter((courier) => allowedCourierIds.includes(courier.courier_company_id));
|
|
16
|
+
}
|
|
17
|
+
function slugify(str) {
|
|
18
|
+
return str
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.trim()
|
|
21
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
22
|
+
.replace(/\s+/g, '-')
|
|
23
|
+
.replace(/-+/g, '-');
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3NoaXByb2NrZXQvdXRpbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSxnREFVQztBQUVELHNEQU9DO0FBRUQsMEJBT0M7QUE1QkQsU0FBZ0Isa0JBQWtCLENBQUMsUUFBbUI7SUFDbEQsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FDakMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FDNUMsQ0FBQztJQUVGLElBQUksYUFBYSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFFNUMsT0FBTyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ3RDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM3RCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxTQUFnQixxQkFBcUIsQ0FDakMsUUFBbUIsRUFDbkIsaUJBQTJCO0lBRTNCLE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQy9CLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FDekQsQ0FBQztBQUNOLENBQUM7QUFFRCxTQUFnQixPQUFPLENBQUMsR0FBVztJQUMvQixPQUFPLEdBQUc7U0FDTCxXQUFXLEVBQUU7U0FDYixJQUFJLEVBQUU7U0FDTixPQUFPLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztTQUM1QixPQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQztTQUNwQixPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzdCLENBQUMifQ==
|
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<a href="http://www.shiprocket.in"><img src="https://i.postimg.cc/zGzTRdqp/id-Nga-I3rk-T-logos.png" alt="Markdownify" width="200"></a>
|
|
4
|
+
<br>
|
|
5
|
+
for Medusa 2.0+
|
|
6
|
+
<br>
|
|
7
|
+
</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<img src="https://img.shields.io/npm/v/medusa-cashfree-payment-plugin" alt="medusa-cashfree-payment-plugin">
|
|
11
|
+
<img src="https://img.shields.io/npm/dw/medusa-cashfree-payment-plugin" alt="medusa-cashfree-payment-plugin">
|
|
12
|
+
<img src="https://img.shields.io/github/contributors/SAM-AEL/medusa-cashfree-payment-plugin" alt="medusa-cashfree-payment-plugin">
|
|
13
|
+
<img src="https://img.shields.io/github/last-commit/SAM-AEL/medusa-cashfree-payment-plugin" alt="medusa-cashfree-payment-plugin">
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<h4 align="center">From checkout to doorstep — simplify logistics with <a href="https://www.shiprocket.in" target="_blank">Shiprocket</a> for Medusa.</h4>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="#-features">Features</a> •
|
|
20
|
+
<a href="#%EF%B8%8F-installation">Installation</a> •
|
|
21
|
+
<a href="#-setup-guide">Setup Guide</a> •
|
|
22
|
+
<a href="#-api-reference">API Reference</a> •
|
|
23
|
+
<a href="#-troubleshooting">Troubleshooting</a> •
|
|
24
|
+
<a href="#-contributing">Contributing</a> •
|
|
25
|
+
<a href="#-license">License</a>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
## ✨ Features
|
|
29
|
+
|
|
30
|
+
- 🚚 **Seamless Shipping** - _Create and manage shipments directly from Medusa admin panel_
|
|
31
|
+
|
|
32
|
+
- 💸 **Automated Rate Calculation** - _Fetch real-time courier rates at checkout_
|
|
33
|
+
|
|
34
|
+
- ❌ **Easy Cancellations** - _Cancel shipments instantly from Medusa_
|
|
35
|
+
|
|
36
|
+
- 📦 **Pickup Location Support** - _Configure and use multiple Shiprocket pickup points_
|
|
37
|
+
|
|
38
|
+
- 🌍 **India-first Logistics** - _Optimized for Indian e-commerce and Shiprocket’s courier network_
|
|
39
|
+
|
|
40
|
+
## 📋 Prerequisites
|
|
41
|
+
|
|
42
|
+
- [MedusaJS](https://docs.medusajs.com/) 2 store
|
|
43
|
+
|
|
44
|
+
- [Shiprocket](https://www.shiprocket.in/) account
|
|
45
|
+
|
|
46
|
+
## 🚧 To Do:
|
|
47
|
+
|
|
48
|
+
- 💱 **Return Shipping** - _Initiate Refund and replacement directly through Admin Dashboard_
|
|
49
|
+
|
|
50
|
+
- 🔗 **Webhooks integration** - _Stay updated with shipment updates in Admin Dashboard_
|
|
51
|
+
|
|
52
|
+
- 🔎 **Live Tracking** - _Get shipment status and tracking updates without leaving Medusa Admin Dashboard_
|
|
53
|
+
|
|
54
|
+
- 📚 **Label, Manifest and Invoice** - _Directly accessible in Medusa Admin_
|
|
55
|
+
- **_Rewrite the plugin with more optimizations and code cleanup._**
|
|
56
|
+
|
|
57
|
+
## 🛠️ Installation
|
|
58
|
+
|
|
59
|
+
#### Step 1: Install the Plugin
|
|
60
|
+
|
|
61
|
+
Choose your preferred package manager:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
|
|
65
|
+
# npm
|
|
66
|
+
|
|
67
|
+
npm install medusa-shiprocket-fulfillment-plugin
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# yarn
|
|
72
|
+
|
|
73
|
+
yarn add medusa-shiprocket-fulfillment-plugin
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# pnpm
|
|
78
|
+
|
|
79
|
+
pnpm add medusa-shiprocket-fulfillment-plugin
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Step 2: Configure Plugin
|
|
84
|
+
|
|
85
|
+
Add the plugin to your `medusa-config.js`:
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
module.exports = defineConfig({
|
|
89
|
+
|
|
90
|
+
// other configs
|
|
91
|
+
|
|
92
|
+
modules: [
|
|
93
|
+
|
|
94
|
+
// other plugins
|
|
95
|
+
|
|
96
|
+
{
|
|
97
|
+
resolve: "@medusajs/medusa/fulfillment",
|
|
98
|
+
options: {
|
|
99
|
+
providers: [
|
|
100
|
+
{
|
|
101
|
+
resolve:
|
|
102
|
+
"medusa-shiprocket-fulfillment-plugin/providers/shiprocket",
|
|
103
|
+
id: "shiprocket",
|
|
104
|
+
options: {
|
|
105
|
+
email: process.env.SHIPROCKET_EMAIL,
|
|
106
|
+
password: process.env.SHIPROCKET_PASSWORD,
|
|
107
|
+
pickup_location: process.env.SHIPROCKET_PICKUP_LOCATION,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
plugins: [
|
|
115
|
+
{
|
|
116
|
+
resolve: "medusa-shiprocket-fulfillment-plugin",
|
|
117
|
+
options: {
|
|
118
|
+
email: process.env.SHIPROCKET_EMAIL,
|
|
119
|
+
password: process.env.SHIPROCKET_PASSWORD,
|
|
120
|
+
pickup_location: process.env.SHIPROCKET_PICKUP_LOCATION,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Step 3: Environment Variables
|
|
128
|
+
|
|
129
|
+
Create or update your `.env` file:
|
|
130
|
+
|
|
131
|
+
```env
|
|
132
|
+
|
|
133
|
+
# Shiprocket Configuration
|
|
134
|
+
|
|
135
|
+
SHIPROCKET_EMAIL=your email
|
|
136
|
+
SHIPROCKET_PASSWORD=password
|
|
137
|
+
SHIPROCKET_PICKUP_LOCATION=Primary
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
> ⚠️ **Security Note**: Never commit your production credentials to version control.
|
|
142
|
+
|
|
143
|
+
### ⚙️ Configuration Options
|
|
144
|
+
|
|
145
|
+
| Option | Type | Required | Default | Description |
|
|
146
|
+
| ----------------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------ |
|
|
147
|
+
| `email` | string | ✅ | - | Your Shiprocket account email |
|
|
148
|
+
| `password` | string | ✅ | - | Your Shiprocket account password |
|
|
149
|
+
| `pickup_location` | string | ✅ | - | The Shiprocket pickup location name (must match one created in Shiprocket dashboard) |
|
|
150
|
+
|
|
151
|
+
### 🎯 Setup Guide
|
|
152
|
+
|
|
153
|
+
### Enable Fulfillment Provider
|
|
154
|
+
|
|
155
|
+
1. Navigate to **Medusa Admin → Settings → Regions**
|
|
156
|
+
2. Select your target region - India (or any region you want Shiprocket to serve).
|
|
157
|
+
3. In **Fulfillment Providers**, select `shiprocket`.
|
|
158
|
+
4. Click **Save Changes**.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Configure Shiprocket Credentials
|
|
163
|
+
|
|
164
|
+
1. Go to your [Shiprocket Dashboard](https://app.shiprocket.in/).
|
|
165
|
+
2. Ensure you have:
|
|
166
|
+
- **Email** and **Password** of your Shiprocket account.
|
|
167
|
+
- At least one **Pickup Location** set up (e.g., `Primary`).
|
|
168
|
+
3. Add credentials to your `.env` file:
|
|
169
|
+
|
|
170
|
+
### 🔧 API Reference
|
|
171
|
+
|
|
172
|
+
This plugin implements the complete `AbstractFulfillmentProvider` interface:
|
|
173
|
+
|
|
174
|
+
#### Core Methods
|
|
175
|
+
|
|
176
|
+
- `createFulfillment()` - Create a fulfillment in Shiprocket.
|
|
177
|
+
- `cancelFulfillment()` - Cancel a fulfillment in Shiprocket.
|
|
178
|
+
- `getFulfillmentDocuments()` - Retrieve labels, manifests, and invoices for a fulfillment.
|
|
179
|
+
- `getTrackingInfo()` - Get tracking information for a shipment.
|
|
180
|
+
|
|
181
|
+
#### Utility Methods
|
|
182
|
+
|
|
183
|
+
- `calculateShippingRate()` - Calculate shipping rates for an order.
|
|
184
|
+
- `createReturn()` - Create a return shipment in Shiprocket.
|
|
185
|
+
- `generateLabel()` - Generate shipping label for a fulfillment.
|
|
186
|
+
- `generateInvoice()` - Generate invoice for a fulfillment.
|
|
187
|
+
|
|
188
|
+
### 🐛 Troubleshooting
|
|
189
|
+
|
|
190
|
+
**_Plugin not appearing in admin_**
|
|
191
|
+
|
|
192
|
+
- Follow the setup and reload the server.
|
|
193
|
+
|
|
194
|
+
**_Admin UI Widget not working_**
|
|
195
|
+
|
|
196
|
+
- Add the plugin to plugin import in medusa-config. reload the server.
|
|
197
|
+
|
|
198
|
+
### Getting Help
|
|
199
|
+
|
|
200
|
+
- 📖 [Shiprocket API Documentation](https://api.shiprocket.in/)
|
|
201
|
+
|
|
202
|
+
- 💬 [MedusaJS Discord](https://discord.gg/medusajs)
|
|
203
|
+
|
|
204
|
+
- 🐛 [Report Issues](https://github.com/SAM-AEL/medusa-shiprocket-fulfillment-plugin/issues)
|
|
205
|
+
|
|
206
|
+
### 🤝 Contributing
|
|
207
|
+
|
|
208
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
209
|
+
|
|
210
|
+
1. Fork the repository
|
|
211
|
+
|
|
212
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
213
|
+
|
|
214
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
215
|
+
|
|
216
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
217
|
+
|
|
218
|
+
5. Open a Pull Request
|
|
219
|
+
|
|
220
|
+
### 📄 License
|
|
221
|
+
|
|
222
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
223
|
+
|
|
224
|
+
### 🙏 Acknowledgments
|
|
225
|
+
|
|
226
|
+
- [MedusaJS](https://medusajs.com/) - for the best open-source e-commerce platform.
|
|
227
|
+
|
|
228
|
+
- [Shiprocket](https://www.shiprocket.in/) - for making the life of a shipper easier.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
<h1 align="center">
|
|
233
|
+
<br>
|
|
234
|
+
Thank you 🫶
|
|
235
|
+
<br>
|
|
236
|
+
</h1>
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "medusa-shiprocket-fulfillment-plugin",
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "Shiprocket Fulfillment Provider Plugin for MedusaJS 2",
|
|
5
|
+
"author": "SAM-AEL",
|
|
6
|
+
"homepage": "https://github.com/SAM-AEL",
|
|
7
|
+
"repository": "https://github.com/SAM-AEL/medusa-shiprocket-fulfillment-plugin",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"files": [
|
|
10
|
+
".medusa/server"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
15
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
16
|
+
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
17
|
+
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|
|
18
|
+
"./*": "./.medusa/server/src/*.js"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"medusa",
|
|
22
|
+
"plugin",
|
|
23
|
+
"medusa-plugin",
|
|
24
|
+
"medusa-v2",
|
|
25
|
+
"medusa-plugin-shipping"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "medusa plugin:build",
|
|
29
|
+
"dev": "medusa plugin:develop",
|
|
30
|
+
"prepublishOnly": "medusa plugin:build"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@medusajs/admin-sdk": "2.4.0",
|
|
34
|
+
"@medusajs/cli": "2.4.0",
|
|
35
|
+
"@medusajs/framework": "2.4.0",
|
|
36
|
+
"@medusajs/icons": "2.4.0",
|
|
37
|
+
"@medusajs/medusa": "2.4.0",
|
|
38
|
+
"@medusajs/test-utils": "2.4.0",
|
|
39
|
+
"@medusajs/ui": "4.0.4",
|
|
40
|
+
"@mikro-orm/cli": "6.4.3",
|
|
41
|
+
"@mikro-orm/core": "6.4.3",
|
|
42
|
+
"@mikro-orm/knex": "6.4.3",
|
|
43
|
+
"@mikro-orm/migrations": "6.4.3",
|
|
44
|
+
"@mikro-orm/postgresql": "6.4.3",
|
|
45
|
+
"@swc/core": "1.5.7",
|
|
46
|
+
"@types/node": "^20.0.0",
|
|
47
|
+
"@types/react": "^18.3.2",
|
|
48
|
+
"@types/react-dom": "^18.2.25",
|
|
49
|
+
"awilix": "^8.0.1",
|
|
50
|
+
"pg": "^8.13.0",
|
|
51
|
+
"prop-types": "^15.8.1",
|
|
52
|
+
"react": "^18.2.0",
|
|
53
|
+
"react-dom": "^18.2.0",
|
|
54
|
+
"ts-node": "^10.9.2",
|
|
55
|
+
"typescript": "^5.6.2",
|
|
56
|
+
"vite": "^5.2.11",
|
|
57
|
+
"yalc": "^1.0.0-pre.53"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@medusajs/admin-sdk": "2.4.0",
|
|
61
|
+
"@medusajs/cli": "2.4.0",
|
|
62
|
+
"@medusajs/framework": "2.4.0",
|
|
63
|
+
"@medusajs/icons": "2.4.0",
|
|
64
|
+
"@medusajs/medusa": "2.4.0",
|
|
65
|
+
"@medusajs/test-utils": "2.4.0",
|
|
66
|
+
"@medusajs/ui": "4.0.3",
|
|
67
|
+
"@mikro-orm/cli": "6.4.3",
|
|
68
|
+
"@mikro-orm/core": "6.4.3",
|
|
69
|
+
"@mikro-orm/knex": "6.4.3",
|
|
70
|
+
"@mikro-orm/migrations": "6.4.3",
|
|
71
|
+
"@mikro-orm/postgresql": "6.4.3",
|
|
72
|
+
"awilix": "^8.0.1",
|
|
73
|
+
"pg": "^8.13.0"
|
|
74
|
+
},
|
|
75
|
+
"engines": {
|
|
76
|
+
"node": ">=20"
|
|
77
|
+
}
|
|
78
|
+
}
|