medusa-pos-plugin 0.0.1

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.
Files changed (36) hide show
  1. package/.medusa/server/src/admin/index.js +23 -0
  2. package/.medusa/server/src/admin/index.mjs +24 -0
  3. package/.medusa/server/src/api/admin/pos/catalog/route.js +139 -0
  4. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/confirm-lite/route.js +41 -0
  5. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/customer/route.js +68 -0
  6. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/finalize/route.js +424 -0
  7. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/items/route.js +452 -0
  8. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/items/update/route.js +137 -0
  9. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/manual-discount/route.js +386 -0
  10. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/promotions/route.js +59 -0
  11. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/route.js +178 -0
  12. package/.medusa/server/src/api/admin/pos/draft-orders/[id]/wallet-debit/route.js +220 -0
  13. package/.medusa/server/src/api/admin/pos/draft-orders/route.js +193 -0
  14. package/.medusa/server/src/api/admin/pos/manual-discounts/route.js +76 -0
  15. package/.medusa/server/src/api/admin/pos/orders/[id]/fulfill/route.js +103 -0
  16. package/.medusa/server/src/api/admin/pos/orders/[id]/returns/route.js +512 -0
  17. package/.medusa/server/src/api/admin/pos/orders/fulfill-pos-items.js +63 -0
  18. package/.medusa/server/src/api/admin/pos/orders/validators.js +62 -0
  19. package/.medusa/server/src/api/admin/pos/payments/config/route.js +15 -0
  20. package/.medusa/server/src/api/admin/pos/payments/device/[orderId]/route.js +39 -0
  21. package/.medusa/server/src/api/admin/pos/payments/device/cancel/route.js +27 -0
  22. package/.medusa/server/src/api/admin/pos/payments/device/route.js +107 -0
  23. package/.medusa/server/src/api/admin/pos/payments/qr/[qrId]/close/route.js +36 -0
  24. package/.medusa/server/src/api/admin/pos/payments/qr/[qrId]/route.js +42 -0
  25. package/.medusa/server/src/api/admin/pos/payments/qr/route.js +78 -0
  26. package/.medusa/server/src/index.js +8 -0
  27. package/.medusa/server/src/types.js +3 -0
  28. package/.medusa/server/src/utils/pos-draft-edit.js +178 -0
  29. package/.medusa/server/src/utils/pos-finalize.js +166 -0
  30. package/.medusa/server/src/utils/pos-inventory.js +265 -0
  31. package/.medusa/server/src/utils/pos-returns.js +339 -0
  32. package/.medusa/server/src/utils/razorpay-pos-device.js +122 -0
  33. package/.medusa/server/src/utils/razorpay-pos.js +134 -0
  34. package/README.md +39 -0
  35. package/index.js +9 -0
  36. package/package.json +82 -0
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const POSMAN_PREFIX = "POSMAN-";
6
+ /**
7
+ * GET /admin/pos/manual-discounts
8
+ * Lists POS manual-discount promotions (POSMAN-*) for POS + external UI.
9
+ * Includes inactive codes (hidden from Admin active promotions).
10
+ */
11
+ async function GET(req, res) {
12
+ const query = (req.query || {});
13
+ const limit = Math.min(Math.max(Number(query.limit) || 50, 1), 100);
14
+ const offset = Math.max(Number(query.offset) || 0, 0);
15
+ const q = (query.q || "").trim().toLowerCase();
16
+ try {
17
+ const promotionModule = req.scope.resolve(utils_1.Modules.PROMOTION);
18
+ // Fetch a window of promotions; filter POSMAN in-process (prefix match).
19
+ const take = Math.min(offset + limit + 200, 500);
20
+ const [rows] = await promotionModule.listAndCountPromotions({}, {
21
+ take,
22
+ skip: 0,
23
+ order: { created_at: "DESC" },
24
+ relations: ["application_method"],
25
+ });
26
+ let manual = (rows || []).filter((p) => {
27
+ const code = String(p.code || "");
28
+ const source = p.metadata?.source;
29
+ return code.startsWith(POSMAN_PREFIX) || source === "pos_manual";
30
+ });
31
+ if (q) {
32
+ manual = manual.filter((p) => {
33
+ const hay = [
34
+ p.code,
35
+ p.metadata?.draft_order_id,
36
+ p.metadata?.applied_by,
37
+ String(p.metadata?.amount ?? ""),
38
+ ]
39
+ .filter(Boolean)
40
+ .join(" ")
41
+ .toLowerCase();
42
+ return hay.includes(q);
43
+ });
44
+ }
45
+ const count = manual.length;
46
+ const page = manual.slice(offset, offset + limit).map((p) => ({
47
+ id: p.id,
48
+ code: p.code,
49
+ status: p.status,
50
+ amount: p.metadata?.amount ??
51
+ p.application_method?.value ??
52
+ null,
53
+ currency_code: p.metadata?.currency_code ??
54
+ p.application_method?.currency_code ??
55
+ null,
56
+ draft_order_id: p.metadata?.draft_order_id ?? null,
57
+ applied_by: p.metadata?.applied_by ?? null,
58
+ applied_at: p.metadata?.applied_at ?? p.created_at ?? null,
59
+ created_at: p.created_at ?? null,
60
+ metadata: p.metadata ?? null,
61
+ }));
62
+ res.json({
63
+ manual_discounts: page,
64
+ count,
65
+ limit,
66
+ offset,
67
+ });
68
+ }
69
+ catch (error) {
70
+ console.error("[pos manual-discounts] GET error:", error);
71
+ res.status(500).json({
72
+ message: error?.message || "Failed to list manual discounts",
73
+ });
74
+ }
75
+ }
76
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Bvcy9tYW51YWwtZGlzY291bnRzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZ0JBLGtCQStFQztBQTlGRCxxREFBbUQ7QUFFbkQsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFBO0FBUS9COzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsR0FBRyxDQUFDLEdBQWtCLEVBQUUsR0FBbUI7SUFDL0QsTUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBYyxDQUFBO0lBQzVDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUNuRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3JELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUU5QyxJQUFJLENBQUM7UUFDSCxNQUFNLGVBQWUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsU0FBUyxDQUsxRCxDQUFBO1FBRUQseUVBQXlFO1FBQ3pFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLEtBQUssR0FBRyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDaEQsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sZUFBZSxDQUFDLHNCQUFzQixDQUN6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
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const validators_1 = require("../../validators");
6
+ const fulfill_pos_items_1 = require("../../fulfill-pos-items");
7
+ const pos_returns_1 = require("../../../../../../utils/pos-returns");
8
+ function isRecord(value) {
9
+ return Boolean(value && typeof value === "object");
10
+ }
11
+ function itemFromUnknown(value) {
12
+ if (!isRecord(value) || typeof value.id !== "string")
13
+ return null;
14
+ const detail = isRecord(value.detail) ? value.detail : null;
15
+ return {
16
+ id: value.id,
17
+ quantity: (0, pos_returns_1.toAmount)(value.quantity) || null,
18
+ detail,
19
+ };
20
+ }
21
+ /**
22
+ * POST /admin/pos/orders/:id/fulfill
23
+ *
24
+ * Record in-store handover as a Medusa fulfillment so later returns are allowed.
25
+ */
26
+ async function POST(req, res) {
27
+ const orderId = req.params.id;
28
+ if (typeof orderId !== "string" || !orderId) {
29
+ res.status(400).json({ message: "Order id is required", type: "INVALID_DATA" });
30
+ return;
31
+ }
32
+ const parseResult = validators_1.PosFulfillOrderSchema.safeParse(req.body ?? {});
33
+ if (!parseResult.success) {
34
+ res.status(400).json({
35
+ message: "Invalid request data",
36
+ errors: parseResult.error.flatten(),
37
+ type: "INVALID_DATA",
38
+ });
39
+ return;
40
+ }
41
+ const body = parseResult.data;
42
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
43
+ const { data } = await query
44
+ .graph({
45
+ entity: "order",
46
+ fields: [
47
+ "id",
48
+ "status",
49
+ "items.id",
50
+ "items.quantity",
51
+ "items.detail.quantity",
52
+ "items.detail.fulfilled_quantity",
53
+ ],
54
+ filters: { id: orderId },
55
+ })
56
+ .catch(() => ({ data: [] }));
57
+ const order = data[0];
58
+ if (!order) {
59
+ res.status(404).json({ message: "Order not found", type: "NOT_FOUND" });
60
+ return;
61
+ }
62
+ const status = typeof order.status === "string" ? order.status : "";
63
+ if (status === "canceled" || status === "cancelled" || status === "draft") {
64
+ res.status(400).json({ message: "Order cannot be fulfilled", type: "NOT_ALLOWED" });
65
+ return;
66
+ }
67
+ const orderItems = (Array.isArray(order.items) ? order.items : [])
68
+ .map((item) => itemFromUnknown(item))
69
+ .filter((item) => !!item);
70
+ const selections = body.items?.length
71
+ ? body.items
72
+ : orderItems.map((item) => ({
73
+ id: item.id,
74
+ quantity: Math.max(1, Math.floor((0, pos_returns_1.toAmount)(item.quantity))),
75
+ }));
76
+ const fulfillItems = (0, pos_returns_1.getItemsToFulfill)(orderItems, selections);
77
+ if (!fulfillItems.length) {
78
+ res.status(200).json({ order_id: orderId, fulfilled: [] });
79
+ return;
80
+ }
81
+ try {
82
+ await (0, fulfill_pos_items_1.fulfillPosOrderItems)({
83
+ container: req.scope,
84
+ query,
85
+ orderId,
86
+ items: fulfillItems,
87
+ locationId: body.location_id,
88
+ actorId: (0, fulfill_pos_items_1.actorIdFromRequest)(req),
89
+ });
90
+ }
91
+ catch (error) {
92
+ const message = (0, pos_returns_1.getThrownErrorMessage)(error, "Failed to fulfill POS order");
93
+ console.error("POS fulfill failed", error);
94
+ res.status(500).json({
95
+ message: "Failed to fulfill POS order",
96
+ error: message,
97
+ type: "INTERNAL_ERROR",
98
+ });
99
+ return;
100
+ }
101
+ res.status(200).json({ order_id: orderId, fulfilled: fulfillItems });
102
+ }
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Bvcy9vcmRlcnMvW2lkXS9mdWxmaWxsL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBc0NBLG9CQW9GQztBQXpIRCxxREFBcUU7QUFDckUsaURBQXdEO0FBQ3hELCtEQUFrRjtBQUNsRixxRUFLNEM7QUFVNUMsU0FBUyxRQUFRLENBQUMsS0FBYztJQUM5QixPQUFPLE9BQU8sQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUE7QUFDcEQsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLEtBQWM7SUFDckMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLEtBQUssQ0FBQyxFQUFFLEtBQUssUUFBUTtRQUFFLE9BQU8sSUFBSSxDQUFBO0lBQ2pFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtJQUMzRCxPQUFPO1FBQ0wsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFO1FBQ1osUUFBUSxFQUFFLElBQUEsc0JBQVEsRUFBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSTtRQUMxQyxNQUFNO0tBQ1AsQ0FBQTtBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0ksS0FBSyxVQUFVLElBQUksQ0FBQyxHQUFrQixFQUFFLEdBQW1CO0lBQ2hFLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFBO0lBQzdCLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDNUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFP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