order-management 0.0.95 → 0.0.97
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/index.js +2446 -397
- package/.medusa/server/src/admin/index.mjs +2450 -401
- package/.medusa/server/src/api/admin/deleted-records-audit/[id]/route.js +30 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/route.js +48 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/stats/route.js +27 -0
- package/.medusa/server/src/api/admin/deleted-records-audit/validators.js +57 -0
- package/.medusa/server/src/api/middlewares/block-refund-until-return-received.js +141 -42
- package/.medusa/server/src/api/middlewares.js +11 -5
- package/.medusa/server/src/helpers/refund-receive-guard.js +102 -1
- package/.medusa/server/src/modules/deleted-records-audit/audited-tables.js +257 -0
- package/.medusa/server/src/modules/deleted-records-audit/index.js +14 -0
- package/.medusa/server/src/modules/deleted-records-audit/migrations/Migration20261008120000.js +81 -0
- package/.medusa/server/src/modules/deleted-records-audit/models/deleted-records-audit.js +15 -0
- package/.medusa/server/src/modules/deleted-records-audit/service.js +164 -0
- package/.medusa/server/src/modules/deleted-records-audit/types.js +3 -0
- package/README.md +79 -2
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const deleted_records_audit_1 = require("../../../../modules/deleted-records-audit");
|
|
5
|
+
/**
|
|
6
|
+
* GET /admin/deleted-records-audit/:id
|
|
7
|
+
* Single audit entry including the full `old_data` snapshot.
|
|
8
|
+
*/
|
|
9
|
+
const GET = async (req, res) => {
|
|
10
|
+
const id = typeof req.params?.id === "string" ? req.params.id.trim() : "";
|
|
11
|
+
if (!id) {
|
|
12
|
+
res.status(400).json({ message: "Audit id is required" });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const service = req.scope.resolve(deleted_records_audit_1.DELETED_RECORDS_AUDIT_MODULE);
|
|
17
|
+
const audit = await service.retrieveAudit(id);
|
|
18
|
+
if (!audit) {
|
|
19
|
+
res.status(404).json({ message: `Deleted record audit ${id} not found` });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
res.status(200).json({ audit });
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const message = error instanceof Error ? error.message : "Failed to load deleted record";
|
|
26
|
+
res.status(500).json({ message });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
exports.GET = GET;
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RlbGV0ZWQtcmVjb3Jkcy1hdWRpdC9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFGQUF3RjtBQUl4Rjs7O0dBR0c7QUFDSSxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbkUsTUFBTSxFQUFFLEdBQUcsT0FBTyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7SUFDekUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ1IsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFBO1FBQ3pELE9BQU07SUFDUixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQW1DLG9EQUE0QixDQUFDLENBQUE7UUFDakcsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQzdDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLFlBQVksRUFBRSxDQUFDLENBQUE7WUFDekUsT0FBTTtRQUNSLENBQUM7UUFDRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBNkMsQ0FBQyxDQUFBO0lBQzVFLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsK0JBQStCLENBQUE7UUFDeEYsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ25DLENBQUM7QUFDSCxDQUFDLENBQUE7QUFuQlksUUFBQSxHQUFHLE9BbUJmIn0=
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const deleted_records_audit_1 = require("../../../modules/deleted-records-audit");
|
|
5
|
+
const validators_1 = require("./validators");
|
|
6
|
+
/**
|
|
7
|
+
* GET /admin/deleted-records-audit
|
|
8
|
+
* Paginated hard-delete audit entries, newest first. `old_data` is only returned by the detail route.
|
|
9
|
+
*/
|
|
10
|
+
const GET = async (req, res) => {
|
|
11
|
+
const parsed = validators_1.AdminListDeletedRecordAuditsSchema.safeParse(req.query ?? {});
|
|
12
|
+
if (!parsed.success) {
|
|
13
|
+
res.status(400).json({
|
|
14
|
+
message: "Invalid filters",
|
|
15
|
+
errors: parsed.error.issues.map((issue) => ({
|
|
16
|
+
path: issue.path.join("."),
|
|
17
|
+
message: issue.message,
|
|
18
|
+
})),
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const query = parsed.data;
|
|
23
|
+
try {
|
|
24
|
+
const service = req.scope.resolve(deleted_records_audit_1.DELETED_RECORDS_AUDIT_MODULE);
|
|
25
|
+
const { audits, count } = await service.listAudits({
|
|
26
|
+
limit: query.limit,
|
|
27
|
+
offset: query.offset,
|
|
28
|
+
q: query.q,
|
|
29
|
+
table_names: (0, validators_1.resolveTableNames)(query),
|
|
30
|
+
date_from: query.date_from,
|
|
31
|
+
date_to: query.date_to,
|
|
32
|
+
source: query.source,
|
|
33
|
+
deleted_by: query.deleted_by,
|
|
34
|
+
});
|
|
35
|
+
res.status(200).json({
|
|
36
|
+
audits,
|
|
37
|
+
count,
|
|
38
|
+
limit: query.limit,
|
|
39
|
+
offset: query.offset,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : "Failed to list deleted records";
|
|
44
|
+
res.status(500).json({ message });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.GET = GET;
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RlbGV0ZWQtcmVjb3Jkcy1hdWRpdC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxrRkFBcUY7QUFHckYsNkNBQW9GO0FBU3BGOzs7R0FHRztBQUNJLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLE1BQU0sR0FBRywrQ0FBa0MsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUM1RSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25CLE9BQU8sRUFBRSxpQkFBaUI7WUFDMUIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDMUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDMUIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO2FBQ3ZCLENBQUMsQ0FBQztTQUNKLENBQUMsQ0FBQTtRQUNGLE9BQU07SUFDUixDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQTtJQUN6QixJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBbUMsb0RBQTRCLENBQUMsQ0FBQTtRQUNqRyxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQztZQUNqRCxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDbEIsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1lBQ3BCLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNWLFdBQVcsRUFBRSxJQUFBLDhCQUFpQixFQUFDLEtBQUssQ0FBQztZQUNyQyxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7WUFDMUIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNwQixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7U0FDN0IsQ0FBQyxDQUFBO1FBQ0YsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDbkIsTUFBTTtZQUNOLEtBQUs7WUFDTCxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDbEIsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1NBQ0UsQ0FBQyxDQUFBO0lBQzNCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsZ0NBQWdDLENBQUE7UUFDekYsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ25DLENBQUM7QUFDSCxDQUFDLENBQUE7QUFwQ1ksUUFBQSxHQUFHLE9Bb0NmIn0=
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const deleted_records_audit_1 = require("../../../../modules/deleted-records-audit");
|
|
5
|
+
const validators_1 = require("../validators");
|
|
6
|
+
/**
|
|
7
|
+
* GET /admin/deleted-records-audit/stats
|
|
8
|
+
* All-time aggregates for the summary cards plus distinct source / deleted_by values for filters.
|
|
9
|
+
*/
|
|
10
|
+
const GET = async (req, res) => {
|
|
11
|
+
const parsed = validators_1.AdminDeletedRecordAuditStatsSchema.safeParse(req.query ?? {});
|
|
12
|
+
if (!parsed.success) {
|
|
13
|
+
res.status(400).json({ message: "Invalid today_start" });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const service = req.scope.resolve(deleted_records_audit_1.DELETED_RECORDS_AUDIT_MODULE);
|
|
18
|
+
const stats = await service.getStats({ today_start: parsed.data.today_start });
|
|
19
|
+
res.status(200).json({ stats });
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const message = error instanceof Error ? error.message : "Failed to load deleted records stats";
|
|
23
|
+
res.status(500).json({ message });
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.GET = GET;
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2RlbGV0ZWQtcmVjb3Jkcy1hdWRpdC9zdGF0cy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxRkFBd0Y7QUFHeEYsOENBQWtFO0FBRWxFOzs7R0FHRztBQUNJLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLE1BQU0sR0FBRywrQ0FBa0MsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUM1RSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLENBQUMsQ0FBQTtRQUN4RCxPQUFNO0lBQ1IsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFtQyxvREFBNEIsQ0FBQyxDQUFBO1FBQ2pHLE1BQU0sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUE7UUFDOUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQWtELENBQUMsQ0FBQTtJQUNqRixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHNDQUFzQyxDQUFBO1FBQy9GLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNuQyxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBZlksUUFBQSxHQUFHLE9BZWYifQ==
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AdminDeletedRecordAuditStatsSchema = exports.AdminListDeletedRecordAuditsSchema = void 0;
|
|
4
|
+
exports.resolveTableNames = resolveTableNames;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const optionalDate = zod_1.z
|
|
7
|
+
.string()
|
|
8
|
+
.trim()
|
|
9
|
+
.optional()
|
|
10
|
+
.transform((value, ctx) => {
|
|
11
|
+
if (!value)
|
|
12
|
+
return undefined;
|
|
13
|
+
const date = new Date(value);
|
|
14
|
+
if (Number.isNaN(date.getTime())) {
|
|
15
|
+
ctx.addIssue({ code: "custom", message: `Invalid date: ${value}` });
|
|
16
|
+
return zod_1.z.NEVER;
|
|
17
|
+
}
|
|
18
|
+
return date;
|
|
19
|
+
});
|
|
20
|
+
const optionalTrimmed = zod_1.z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.transform((value) => {
|
|
24
|
+
const trimmed = value?.trim();
|
|
25
|
+
return trimmed ? trimmed : undefined;
|
|
26
|
+
});
|
|
27
|
+
const TABLE_NAME_PATTERN = /^[a-z0-9_]+$/;
|
|
28
|
+
exports.AdminListDeletedRecordAuditsSchema = zod_1.z.object({
|
|
29
|
+
limit: zod_1.z.coerce.number().int().positive().max(100).default(50),
|
|
30
|
+
offset: zod_1.z.coerce.number().int().nonnegative().default(0),
|
|
31
|
+
q: optionalTrimmed,
|
|
32
|
+
table_name: optionalTrimmed,
|
|
33
|
+
/** Comma-separated list, used when filtering by a whole category. */
|
|
34
|
+
table_names: optionalTrimmed,
|
|
35
|
+
date_from: optionalDate,
|
|
36
|
+
date_to: optionalDate,
|
|
37
|
+
source: optionalTrimmed,
|
|
38
|
+
deleted_by: optionalTrimmed,
|
|
39
|
+
});
|
|
40
|
+
function resolveTableNames(query) {
|
|
41
|
+
const names = new Set();
|
|
42
|
+
if (query.table_name)
|
|
43
|
+
names.add(query.table_name);
|
|
44
|
+
if (query.table_names) {
|
|
45
|
+
for (const part of query.table_names.split(",")) {
|
|
46
|
+
const name = part.trim();
|
|
47
|
+
if (name)
|
|
48
|
+
names.add(name);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const valid = [...names].filter((name) => TABLE_NAME_PATTERN.test(name));
|
|
52
|
+
return valid.length ? valid : undefined;
|
|
53
|
+
}
|
|
54
|
+
exports.AdminDeletedRecordAuditStatsSchema = zod_1.z.object({
|
|
55
|
+
today_start: optionalDate,
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYWRtaW4vZGVsZXRlZC1yZWNvcmRzLWF1ZGl0L3ZhbGlkYXRvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBeUNBLDhDQVdDO0FBcERELDZCQUF1QjtBQUV2QixNQUFNLFlBQVksR0FBRyxPQUFDO0tBQ25CLE1BQU0sRUFBRTtLQUNSLElBQUksRUFBRTtLQUNOLFFBQVEsRUFBRTtLQUNWLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtJQUN4QixJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFBO0lBQzVCLE1BQU0sSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzVCLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ2pDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxpQkFBaUIsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBQ25FLE9BQU8sT0FBQyxDQUFDLEtBQUssQ0FBQTtJQUNoQixDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUE7QUFDYixDQUFDLENBQUMsQ0FBQTtBQUVKLE1BQU0sZUFBZSxHQUFHLE9BQUM7S0FDdEIsTUFBTSxFQUFFO0tBQ1IsUUFBUSxFQUFFO0tBQ1YsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7SUFDbkIsTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFBO0lBQzdCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQTtBQUN0QyxDQUFDLENBQUMsQ0FBQTtBQUVKLE1BQU0sa0JBQWtCLEdBQUcsY0FBYyxDQUFBO0FBRTVCLFFBQUEsa0NBQWtDLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUN6RCxLQUFLLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxNQUFNLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUMsRUFBRSxlQUFlO0lBQ2xCLFVBQVUsRUFBRSxlQUFlO0lBQzNCLHFFQUFxRTtJQUNyRSxXQUFXLEVBQUUsZUFBZTtJQUM1QixTQUFTLEVBQUUsWUFBWTtJQUN2QixPQUFPLEVBQUUsWUFBWTtJQUNyQixNQUFNLEVBQUUsZUFBZTtJQUN2QixVQUFVLEVBQUUsZUFBZTtDQUM1QixDQUFDLENBQUE7QUFJRixTQUFnQixpQkFBaUIsQ0FBQyxLQUF3QztJQUN4RSxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFBO0lBQy9CLElBQUksS0FBSyxDQUFDLFVBQVU7UUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNqRCxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN0QixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDaEQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1lBQ3hCLElBQUksSUFBSTtnQkFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzNCLENBQUM7SUFDSCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7SUFDeEUsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQTtBQUN6QyxDQUFDO0FBRVksUUFBQSxrQ0FBa0MsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3pELFdBQVcsRUFBRSxZQUFZO0NBQzFCLENBQUMsQ0FBQSJ9
|
|
@@ -3,27 +3,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.blockRefundUntilReturnReceived = blockRefundUntilReturnReceived;
|
|
4
4
|
const utils_1 = require("@medusajs/framework/utils");
|
|
5
5
|
const refund_receive_guard_1 = require("../../helpers/refund-receive-guard");
|
|
6
|
+
function getKnex(req) {
|
|
7
|
+
return req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
8
|
+
}
|
|
6
9
|
function paymentIdFromRequest(req) {
|
|
7
10
|
const raw = req.params?.id;
|
|
8
|
-
const
|
|
9
|
-
|
|
11
|
+
const fromParams = typeof raw === "string" ? raw.trim() : "";
|
|
12
|
+
if (fromParams) {
|
|
13
|
+
return fromParams;
|
|
14
|
+
}
|
|
15
|
+
// Wildcard matchers (/admin/payments/*/refund) do not populate :id
|
|
16
|
+
const path = (typeof req.originalUrl === "string" && req.originalUrl) ||
|
|
17
|
+
(typeof req.url === "string" && req.url) ||
|
|
18
|
+
(typeof req.path === "string" && req.path) ||
|
|
19
|
+
"";
|
|
20
|
+
const match = path.match(/\/admin\/payments\/([^/?#]+)\/refund/i);
|
|
21
|
+
const fromPath = match?.[1]?.trim();
|
|
22
|
+
return fromPath || undefined;
|
|
10
23
|
}
|
|
11
24
|
async function resolveOrderIdForPayment(paymentId, req) {
|
|
12
25
|
const paymentModule = req.scope.resolve(utils_1.Modules.PAYMENT);
|
|
13
|
-
const payments = await paymentModule.listPayments({ id: [paymentId] }, {
|
|
26
|
+
const payments = await paymentModule.listPayments({ id: [paymentId] }, { take: 1 });
|
|
14
27
|
const paymentList = Array.isArray(payments) ? payments : [];
|
|
15
28
|
const paymentRow = paymentList[0];
|
|
16
29
|
if (!paymentRow) {
|
|
17
30
|
return null;
|
|
18
31
|
}
|
|
19
|
-
|
|
20
|
-
let collectionId = paymentRow.payment_collection_id?.trim() ||
|
|
21
|
-
sessionObj?.payment_collection_id?.trim() ||
|
|
22
|
-
null;
|
|
32
|
+
let collectionId = paymentRow.payment_collection_id?.trim() || null;
|
|
23
33
|
if (!collectionId && typeof paymentRow.payment_session_id === "string") {
|
|
24
34
|
const sessionId = paymentRow.payment_session_id.trim();
|
|
25
35
|
if (sessionId) {
|
|
26
|
-
const sessions = await paymentModule
|
|
36
|
+
const sessions = await paymentModule
|
|
37
|
+
.listPaymentSessions({ id: [sessionId] })
|
|
38
|
+
.catch(() => []);
|
|
27
39
|
const sessionList = Array.isArray(sessions) ? sessions : [];
|
|
28
40
|
const session = sessionList[0];
|
|
29
41
|
if (session?.payment_collection_id) {
|
|
@@ -34,34 +46,114 @@ async function resolveOrderIdForPayment(paymentId, req) {
|
|
|
34
46
|
if (!collectionId) {
|
|
35
47
|
return null;
|
|
36
48
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
try {
|
|
50
|
+
const knex = getKnex(req);
|
|
51
|
+
const rows = await knex("order_payment_collection")
|
|
52
|
+
.select("order_id")
|
|
53
|
+
.where("payment_collection_id", collectionId)
|
|
54
|
+
.whereNull("deleted_at")
|
|
55
|
+
.limit(1);
|
|
56
|
+
const orderId = rows?.[0]?.order_id;
|
|
57
|
+
if (typeof orderId === "string" && orderId.trim()) {
|
|
58
|
+
return orderId.trim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Fall through
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
async function loadRmaForOrder(orderId, req) {
|
|
67
|
+
const knex = getKnex(req);
|
|
68
|
+
const returnRows = (await knex("return")
|
|
69
|
+
.select(["id", "status", "exchange_id"])
|
|
70
|
+
.where("order_id", orderId)
|
|
71
|
+
.whereNull("deleted_at"));
|
|
72
|
+
const returns = returnRows
|
|
73
|
+
.filter((row) => typeof row.id === "string")
|
|
74
|
+
.map((row) => ({
|
|
75
|
+
id: row.id,
|
|
76
|
+
status: row.status,
|
|
77
|
+
exchange_id: row.exchange_id ?? null,
|
|
78
|
+
}));
|
|
79
|
+
const exchangeRows = (await knex("order_exchange")
|
|
80
|
+
.select(["id", "canceled_at", "return_id"])
|
|
81
|
+
.where("order_id", orderId)
|
|
82
|
+
.whereNull("deleted_at"));
|
|
83
|
+
const exchanges = exchangeRows
|
|
84
|
+
.filter((row) => typeof row.id === "string")
|
|
85
|
+
.map((row) => {
|
|
86
|
+
const returnId = row.return_id ?? null;
|
|
87
|
+
const linked = (returnId ? returns.find((r) => r.id === returnId) : null) ?? null;
|
|
88
|
+
return {
|
|
89
|
+
id: row.id,
|
|
90
|
+
canceled_at: row.canceled_at ?? null,
|
|
91
|
+
return_id: returnId,
|
|
92
|
+
return: linked,
|
|
93
|
+
};
|
|
42
94
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
95
|
+
return { returns, exchanges };
|
|
96
|
+
}
|
|
97
|
+
async function loadWalletSettleEvidence(orderId, req) {
|
|
98
|
+
const knex = getKnex(req);
|
|
99
|
+
let orderTransactions = [];
|
|
100
|
+
try {
|
|
101
|
+
const txRows = (await knex("order_transaction")
|
|
102
|
+
.select(["reference", "reference_id"])
|
|
103
|
+
.where("order_id", orderId)
|
|
104
|
+
.whereNull("deleted_at"));
|
|
105
|
+
orderTransactions = txRows
|
|
106
|
+
.filter((row) => (row.reference ?? "").trim() === "refund")
|
|
107
|
+
.map((row) => ({
|
|
108
|
+
reference: row.reference,
|
|
109
|
+
reference_id: row.reference_id,
|
|
110
|
+
}));
|
|
57
111
|
}
|
|
58
|
-
|
|
112
|
+
catch {
|
|
113
|
+
orderTransactions = [];
|
|
114
|
+
}
|
|
115
|
+
const paymentRefunds = [];
|
|
116
|
+
try {
|
|
117
|
+
const result = await knex.raw(`
|
|
118
|
+
SELECT r.created_by, r.note, r.metadata
|
|
119
|
+
FROM refund r
|
|
120
|
+
INNER JOIN payment p ON p.id = r.payment_id AND p.deleted_at IS NULL
|
|
121
|
+
INNER JOIN order_payment_collection opc
|
|
122
|
+
ON opc.payment_collection_id = p.payment_collection_id
|
|
123
|
+
AND opc.deleted_at IS NULL
|
|
124
|
+
WHERE opc.order_id = ?
|
|
125
|
+
AND r.deleted_at IS NULL
|
|
126
|
+
`, [orderId]);
|
|
127
|
+
const rows = (result && typeof result === "object" && "rows" in result
|
|
128
|
+
? result.rows
|
|
129
|
+
: Array.isArray(result)
|
|
130
|
+
? result
|
|
131
|
+
: []);
|
|
132
|
+
for (const row of rows) {
|
|
133
|
+
paymentRefunds.push({
|
|
134
|
+
created_by: row.created_by,
|
|
135
|
+
note: row.note,
|
|
136
|
+
metadata: row.metadata ?? null,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Soft-fail: still enforce return/exchange checks
|
|
142
|
+
}
|
|
143
|
+
return { orderTransactions, paymentRefunds };
|
|
59
144
|
}
|
|
60
145
|
/**
|
|
61
|
-
* Block Medusa core POST /admin/payments/:id/refund while
|
|
62
|
-
*
|
|
146
|
+
* Block Medusa core POST /admin/payments/:id/refund while return/exchange is
|
|
147
|
+
* unreceived, or when the order was already settled to the customer wallet.
|
|
63
148
|
*/
|
|
64
149
|
async function blockRefundUntilReturnReceived(req, res, next) {
|
|
150
|
+
// Dual matchers can both hit; only evaluate once per request.
|
|
151
|
+
const checkedKey = "__om_refund_rma_checked";
|
|
152
|
+
const reqFlags = req;
|
|
153
|
+
if (reqFlags[checkedKey]) {
|
|
154
|
+
return next();
|
|
155
|
+
}
|
|
156
|
+
reqFlags[checkedKey] = true;
|
|
65
157
|
const paymentId = paymentIdFromRequest(req);
|
|
66
158
|
if (!paymentId) {
|
|
67
159
|
return next();
|
|
@@ -69,29 +161,36 @@ async function blockRefundUntilReturnReceived(req, res, next) {
|
|
|
69
161
|
try {
|
|
70
162
|
const orderId = await resolveOrderIdForPayment(paymentId, req);
|
|
71
163
|
if (!orderId) {
|
|
72
|
-
|
|
164
|
+
res.status(400).json({
|
|
165
|
+
message: (0, refund_receive_guard_1.refundBlockedOrderUnresolvedMessage)(),
|
|
166
|
+
type: "NOT_ALLOWED",
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
73
169
|
}
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
170
|
+
const { returns: returnList, exchanges: exchangeList } = await loadRmaForOrder(orderId, req);
|
|
171
|
+
const { orderTransactions, paymentRefunds } = await loadWalletSettleEvidence(orderId, req);
|
|
172
|
+
const decision = (0, refund_receive_guard_1.shouldBlockRefundForRma)({
|
|
173
|
+
returns: returnList,
|
|
174
|
+
exchanges: exchangeList,
|
|
175
|
+
orderTransactions,
|
|
176
|
+
paymentRefunds,
|
|
177
|
+
});
|
|
178
|
+
if (!decision.blocked) {
|
|
82
179
|
return next();
|
|
83
180
|
}
|
|
84
181
|
res.status(400).json({
|
|
85
|
-
message:
|
|
182
|
+
message: decision.message,
|
|
86
183
|
type: "NOT_ALLOWED",
|
|
87
184
|
});
|
|
88
185
|
}
|
|
89
186
|
catch (err) {
|
|
90
|
-
const message = err instanceof Error
|
|
187
|
+
const message = err instanceof Error
|
|
188
|
+
? err.message
|
|
189
|
+
: "Failed to validate refund against return status";
|
|
91
190
|
res.status(500).json({
|
|
92
191
|
message,
|
|
93
192
|
type: "INTERNAL_ERROR",
|
|
94
193
|
});
|
|
95
194
|
}
|
|
96
195
|
}
|
|
97
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
196
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2stcmVmdW5kLXVudGlsLXJldHVybi1yZWNlaXZlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvbWlkZGxld2FyZXMvYmxvY2stcmVmdW5kLXVudGlsLXJldHVybi1yZWNlaXZlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQXNQQSx3RUErREM7QUEvU0QscURBR2tDO0FBQ2xDLDZFQU8yQztBQTBCM0MsU0FBUyxPQUFPLENBQUMsR0FBa0I7SUFDakMsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBVyxpQ0FBeUIsQ0FBQyxhQUFhLENBQUMsQ0FBQTtBQUM3RSxDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxHQUFrQjtJQUM5QyxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQTtJQUMxQixNQUFNLFVBQVUsR0FBRyxPQUFPLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQzVELElBQUksVUFBVSxFQUFFLENBQUM7UUFDZixPQUFPLFVBQVUsQ0FBQTtJQUNuQixDQUFDO0lBQ0QsbUVBQW1FO0lBQ25FLE1BQU0sSUFBSSxHQUNSLENBQUMsT0FBTyxHQUFHLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDO1FBQ3hELENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDO1FBQ3hDLENBQUMsT0FBTyxHQUFHLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQzFDLEVBQUUsQ0FBQTtJQUNKLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQTtJQUNqRSxNQUFNLFFBQVEsR0FBRyxLQUFLLEVBQUUs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
|
|
@@ -8,24 +8,30 @@ exports.default = (0, http_1.defineMiddlewares)({
|
|
|
8
8
|
routes: [
|
|
9
9
|
{
|
|
10
10
|
matcher: "/admin/payments/:id/refund",
|
|
11
|
-
|
|
11
|
+
methods: ["POST"],
|
|
12
|
+
middlewares: [block_refund_until_return_received_1.blockRefundUntilReturnReceived],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
// Wildcard fallback when :id matchers are skipped
|
|
16
|
+
matcher: "/admin/payments/*/refund",
|
|
17
|
+
methods: ["POST"],
|
|
12
18
|
middlewares: [block_refund_until_return_received_1.blockRefundUntilReturnReceived],
|
|
13
19
|
},
|
|
14
20
|
{
|
|
15
21
|
matcher: "/store/returns",
|
|
16
|
-
|
|
22
|
+
methods: ["POST"],
|
|
17
23
|
middlewares: [(0, http_1.validateAndTransformBody)(validators_1.StoreCreateReturnSchema)],
|
|
18
24
|
},
|
|
19
25
|
{
|
|
20
26
|
matcher: "/store/orders/cancel/:order_id",
|
|
21
|
-
|
|
27
|
+
methods: ["POST"],
|
|
22
28
|
middlewares: [(0, http_1.validateAndTransformBody)(cancel_order_1.StoreCancelOrderBodySchema)],
|
|
23
29
|
},
|
|
24
30
|
{
|
|
25
31
|
matcher: "/store/guest-orders/:id/cancel",
|
|
26
|
-
|
|
32
|
+
methods: ["POST"],
|
|
27
33
|
middlewares: [(0, http_1.validateAndTransformBody)(cancel_order_1.StoreCancelOrderBodySchema)],
|
|
28
34
|
},
|
|
29
35
|
],
|
|
30
36
|
});
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBR2lDO0FBQ2pDLHlHQUFpRztBQUNqRywyREFBb0U7QUFDcEUsa0VBQTRFO0FBRTVFLGtCQUFlLElBQUEsd0JBQWlCLEVBQUM7SUFDL0IsTUFBTSxFQUFFO1FBQ047WUFDRSxPQUFPLEVBQUUsNEJBQTRCO1lBQ3JDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUNqQixXQUFXLEVBQUUsQ0FBQyxtRUFBOEIsQ0FBQztTQUM5QztRQUNEO1lBQ0Usa0RBQWtEO1lBQ2xELE9BQU8sRUFBRSwwQkFBMEI7WUFDbkMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ2pCLFdBQVcsRUFBRSxDQUFDLG1FQUE4QixDQUFDO1NBQzlDO1FBQ0Q7WUFDRSxPQUFPLEVBQUUsZ0JBQWdCO1lBQ3pCLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUNqQixXQUFXLEVBQUUsQ0FBQyxJQUFBLCtCQUF3QixFQUFDLG9DQUF1QixDQUFDLENBQUM7U0FDakU7UUFDRDtZQUNFLE9BQU8sRUFBRSxnQ0FBZ0M7WUFDekMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ2pCLFdBQVcsRUFBRSxDQUFDLElBQUEsK0JBQXdCLEVBQUMseUNBQTBCLENBQUMsQ0FBQztTQUNwRTtRQUNEO1lBQ0UsT0FBTyxFQUFFLGdDQUFnQztZQUN6QyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUM7WUFDakIsV0FBVyxFQUFFLENBQUMsSUFBQSwrQkFBd0IsRUFBQyx5Q0FBMEIsQ0FBQyxDQUFDO1NBQ3BFO0tBQ0Y7Q0FDRixDQUFDLENBQUEifQ==
|
|
@@ -1,17 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.refundBlockedByReturnMessage = refundBlockedByReturnMessage;
|
|
4
|
+
exports.refundBlockedByExchangeMessage = refundBlockedByExchangeMessage;
|
|
5
|
+
exports.refundBlockedByWalletSettleMessage = refundBlockedByWalletSettleMessage;
|
|
6
|
+
exports.refundBlockedOrderUnresolvedMessage = refundBlockedOrderUnresolvedMessage;
|
|
7
|
+
exports.isWalletSettleOrderTransaction = isWalletSettleOrderTransaction;
|
|
8
|
+
exports.isWalletSettlePaymentRefund = isWalletSettlePaymentRefund;
|
|
9
|
+
exports.orderHasWalletSettle = orderHasWalletSettle;
|
|
4
10
|
exports.getUnreceivedReturnBlockingRefund = getUnreceivedReturnBlockingRefund;
|
|
11
|
+
exports.shouldBlockRefundForRma = shouldBlockRefundForRma;
|
|
5
12
|
exports.assertReturnReceivedForRefund = assertReturnReceivedForRefund;
|
|
6
13
|
exports.canProcessRefundForReturn = canProcessRefundForReturn;
|
|
7
14
|
const utils_1 = require("@medusajs/framework/utils");
|
|
8
15
|
const return_exchange_guard_1 = require("./return-exchange-guard");
|
|
16
|
+
const WALLET_SETTLE_REFERENCE_PREFIXES = [
|
|
17
|
+
"wallet:exchange:",
|
|
18
|
+
"wallet:return:",
|
|
19
|
+
"wallet:payment:",
|
|
20
|
+
];
|
|
9
21
|
/**
|
|
10
22
|
* Message when a refund is attempted before the return is fully received.
|
|
11
23
|
*/
|
|
12
24
|
function refundBlockedByReturnMessage(status) {
|
|
13
25
|
return `Cannot process a refund while the return is ${status}. Receive the returned items first.`;
|
|
14
26
|
}
|
|
27
|
+
function refundBlockedByExchangeMessage() {
|
|
28
|
+
return "Cannot process a refund while an exchange is in progress. Receive the returned items first.";
|
|
29
|
+
}
|
|
30
|
+
function refundBlockedByWalletSettleMessage() {
|
|
31
|
+
return "Cannot process a payment refund; this order was already settled to the customer wallet.";
|
|
32
|
+
}
|
|
33
|
+
function refundBlockedOrderUnresolvedMessage() {
|
|
34
|
+
return "Cannot process a refund: unable to resolve the order for this payment. Verify the payment is linked to an order.";
|
|
35
|
+
}
|
|
36
|
+
function isWalletSettleOrderTransaction(tx) {
|
|
37
|
+
if ((tx.reference ?? "").trim() !== "refund") {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const refId = (tx.reference_id ?? "").trim();
|
|
41
|
+
return WALLET_SETTLE_REFERENCE_PREFIXES.some((prefix) => refId.startsWith(prefix));
|
|
42
|
+
}
|
|
43
|
+
function isWalletSettlePaymentRefund(refund) {
|
|
44
|
+
if (refund.created_by === "wallet_settle") {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (refund.metadata?.wallet_settle === true) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const note = refund.note ?? "";
|
|
51
|
+
return note.startsWith("wallet_settle:");
|
|
52
|
+
}
|
|
53
|
+
function orderHasWalletSettle(input) {
|
|
54
|
+
if ((input.orderTransactions ?? []).some(isWalletSettleOrderTransaction)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if ((input.paymentRefunds ?? []).some(isWalletSettlePaymentRefund)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
15
62
|
/**
|
|
16
63
|
* First unreceived return that must block a refund (`open` | `requested` | `partially_received`).
|
|
17
64
|
* Exchange-linked returns are included — refunds are blocked until items are received.
|
|
@@ -24,6 +71,60 @@ function getUnreceivedReturnBlockingRefund(returns) {
|
|
|
24
71
|
}
|
|
25
72
|
return null;
|
|
26
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Whether admin payment refund should be blocked for open RMA or prior wallet settle.
|
|
76
|
+
*/
|
|
77
|
+
function shouldBlockRefundForRma(input) {
|
|
78
|
+
if (orderHasWalletSettle({
|
|
79
|
+
orderTransactions: input.orderTransactions,
|
|
80
|
+
paymentRefunds: input.paymentRefunds,
|
|
81
|
+
})) {
|
|
82
|
+
return {
|
|
83
|
+
blocked: true,
|
|
84
|
+
reason: "wallet_settle",
|
|
85
|
+
message: refundBlockedByWalletSettleMessage(),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const blockingReturn = getUnreceivedReturnBlockingRefund(input.returns);
|
|
89
|
+
if (blockingReturn) {
|
|
90
|
+
return {
|
|
91
|
+
blocked: true,
|
|
92
|
+
reason: "return",
|
|
93
|
+
message: refundBlockedByReturnMessage(blockingReturn.status ?? "requested"),
|
|
94
|
+
returnId: blockingReturn.id,
|
|
95
|
+
status: blockingReturn.status ?? undefined,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
for (const exchange of input.exchanges) {
|
|
99
|
+
let linked = exchange.return ?? null;
|
|
100
|
+
if (!linked && exchange.return_id) {
|
|
101
|
+
linked =
|
|
102
|
+
input.returns.find((r) => r.id === exchange.return_id) ?? null;
|
|
103
|
+
}
|
|
104
|
+
const linkedForGuard = linked
|
|
105
|
+
? {
|
|
106
|
+
id: linked.id,
|
|
107
|
+
status: linked.status ?? undefined,
|
|
108
|
+
exchange_id: linked.exchange_id,
|
|
109
|
+
}
|
|
110
|
+
: null;
|
|
111
|
+
if ((0, return_exchange_guard_1.isActiveExchange)({
|
|
112
|
+
id: exchange.id,
|
|
113
|
+
canceled_at: exchange.canceled_at,
|
|
114
|
+
return_id: exchange.return_id,
|
|
115
|
+
return: linkedForGuard,
|
|
116
|
+
}, linkedForGuard)) {
|
|
117
|
+
return {
|
|
118
|
+
blocked: true,
|
|
119
|
+
reason: "exchange",
|
|
120
|
+
message: refundBlockedByExchangeMessage(),
|
|
121
|
+
exchangeId: exchange.id,
|
|
122
|
+
status: linked?.status ?? undefined,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { blocked: false };
|
|
127
|
+
}
|
|
27
128
|
/**
|
|
28
129
|
* Throw NOT_ALLOWED when this return is still unreceived.
|
|
29
130
|
* No return / already received / canceled → allow.
|
|
@@ -45,4 +146,4 @@ function canProcessRefundForReturn(input) {
|
|
|
45
146
|
Boolean(input.has_mapping) &&
|
|
46
147
|
!input.is_refunded);
|
|
47
148
|
}
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmdW5kLXJlY2VpdmUtZ3VhcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaGVscGVycy9yZWZ1bmQtcmVjZWl2ZS1ndWFyZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWtEQSxvRUFFQztBQUVELHdFQUVDO0FBRUQsZ0ZBRUM7QUFFRCxrRkFFQztBQUVELHdFQVVDO0FBRUQsa0VBV0M7QUFFRCxvREFXQztBQU1ELDhFQVNDO0FBS0QsMERBbUVDO0FBTUQsc0VBYUM7QUFLRCw4REFVQztBQS9ORCxxREFBdUQ7QUFDdkQsbUVBR2dDO0FBcUNoQyxNQUFNLGdDQUFnQyxHQUFHO0lBQ3ZDLGtCQUFrQjtJQUNsQixnQkFBZ0I7SUFDaEIsaUJBQWlCO0NBQ1QsQ0FBQTtBQUVWOztHQUVHO0FBQ0gsU0FBZ0IsNEJBQTRCLENBQUMsTUFBYztJQUN6RCxPQUFPLCtDQUErQyxNQUFNLHFDQUFxQyxDQUFBO0FBQ25HLENBQUM7QUFFRCxTQUFnQiw4QkFBOEI7SUFDNUMsT0FBTyw2RkFBNkYsQ0FBQTtBQUN0RyxDQUFDO0FBRUQsU0FBZ0Isa0NBQWtDO0lBQ2hELE9BQU8seUZBQXlGLENBQUE7QUFDbEcsQ0FBQztBQUVELFNBQWdCLG1DQUFtQztJQUNqRCxPQUFPLGtIQUFrSCxDQUFBO0FBQzNILENBQUM7QUFFRCxTQUFnQiw4QkFBOEIsQ0FDNUMsRUFBa0M7SUFFbEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDN0MsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFBO0lBQzVDLE9BQU8sZ0NBQWdDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FDdEQsS0FBSyxDQUFDLFVB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
|