@yoryoboy/bi-mcp 1.16.0 → 1.17.0
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/dist/.tsbuildinfo +1 -1
- package/dist/index.js +34 -1
- package/dist/index.js.map +2 -2
- package/dist/mcp-use.json +2 -2
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-payments.test.js +137 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-payments.test.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-api.js +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-api.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-billing.js +93 -1
- package/dist/src/services/mercadolibre/mercadolibre-billing.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-payments.js +60 -0
- package/dist/src/services/mercadolibre/mercadolibre-payments.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-billing-provisions-by-order.js +284 -0
- package/dist/src/tools/mercadolibre/get-billing-provisions-by-order.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-full-storage-charges.js +183 -0
- package/dist/src/tools/mercadolibre/get-full-storage-charges.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-payment-details.js +322 -0
- package/dist/src/tools/mercadolibre/get-payment-details.js.map +7 -0
- package/dist/src/tools/mercadolibre/index.js +20 -0
- package/dist/src/tools/mercadolibre/index.js.map +2 -2
- package/dist/tests/meli/mercadolibre-billing-provisions.test.js +176 -0
- package/dist/tests/meli/mercadolibre-billing-provisions.test.js.map +2 -2
- package/dist/tests/meli/mercadolibre-payment-details.test.js +356 -0
- package/dist/tests/meli/mercadolibre-payment-details.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-payments.test.js +62 -0
- package/dist/tests/meli/mercadolibre-payments.test.js.map +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { formatMercadoLibreError } from "../../services/mercadolibre/mercadolibre-api.js";
|
|
4
|
+
import {
|
|
5
|
+
getMercadoLibrePaymentDetails,
|
|
6
|
+
getMercadoLibrePaymentDetailsBatch
|
|
7
|
+
} from "../../services/mercadolibre/mercadolibre-payments.js";
|
|
8
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
9
|
+
import {
|
|
10
|
+
asArray,
|
|
11
|
+
asRecord,
|
|
12
|
+
compactDateTime,
|
|
13
|
+
currencyBucket,
|
|
14
|
+
normalizeScalarString,
|
|
15
|
+
normalizeString,
|
|
16
|
+
roundMoney,
|
|
17
|
+
toNumber
|
|
18
|
+
} from "./helpers.js";
|
|
19
|
+
import { resolveMercadoLibreProfileOrSelection } from "./profile-resolution.js";
|
|
20
|
+
import { mercadolibreProfileIdSchemaField } from "./write-helpers.js";
|
|
21
|
+
const MAX_PAYMENT_IDS = 250;
|
|
22
|
+
const paymentIdSchemaField = z.string().trim().min(1).describe("MercadoLibre payment id to inspect.");
|
|
23
|
+
const meliGetPaymentDetailsSchema = z.object({
|
|
24
|
+
profileId: mercadolibreProfileIdSchemaField,
|
|
25
|
+
paymentId: paymentIdSchemaField.optional().describe("Single MercadoLibre payment id to inspect."),
|
|
26
|
+
paymentIds: z.array(paymentIdSchemaField).min(1).max(MAX_PAYMENT_IDS).describe("One or more MercadoLibre payment ids to inspect in parallel (up to 250, processed in chunks of 50).").optional()
|
|
27
|
+
}).superRefine((value, ctx) => {
|
|
28
|
+
const hasPaymentId = Boolean(value.paymentId);
|
|
29
|
+
const hasPaymentIds = Boolean(value.paymentIds?.length);
|
|
30
|
+
if (hasPaymentId === hasPaymentIds) {
|
|
31
|
+
ctx.addIssue({
|
|
32
|
+
code: z.ZodIssueCode.custom,
|
|
33
|
+
message: "Provide exactly one of paymentId or paymentIds.",
|
|
34
|
+
path: ["paymentId"]
|
|
35
|
+
});
|
|
36
|
+
ctx.addIssue({
|
|
37
|
+
code: z.ZodIssueCode.custom,
|
|
38
|
+
message: "Provide exactly one of paymentId or paymentIds.",
|
|
39
|
+
path: ["paymentIds"]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const paymentsSchema = [
|
|
44
|
+
"payment_id",
|
|
45
|
+
"status",
|
|
46
|
+
"status_detail",
|
|
47
|
+
"currency_id",
|
|
48
|
+
"transaction_amount",
|
|
49
|
+
"total_paid_amount",
|
|
50
|
+
"net_received_amount",
|
|
51
|
+
"overpaid_amount",
|
|
52
|
+
"payment_method_id",
|
|
53
|
+
"payment_type_id",
|
|
54
|
+
"installments",
|
|
55
|
+
"date_created",
|
|
56
|
+
"date_last_updated",
|
|
57
|
+
"description",
|
|
58
|
+
"order_id",
|
|
59
|
+
"payer_id",
|
|
60
|
+
"payer_email",
|
|
61
|
+
"payer_type",
|
|
62
|
+
"payer_first_name",
|
|
63
|
+
"payer_last_name",
|
|
64
|
+
"fee_count",
|
|
65
|
+
"fee_total",
|
|
66
|
+
"external_reference"
|
|
67
|
+
];
|
|
68
|
+
const paymentFeeDetailsSchema = ["payment_id", "fee_type", "fee_amount"];
|
|
69
|
+
function createCurrencyTotals() {
|
|
70
|
+
return {
|
|
71
|
+
count: 0,
|
|
72
|
+
transaction_amount: 0,
|
|
73
|
+
total_paid_amount: 0,
|
|
74
|
+
net_received_amount: 0,
|
|
75
|
+
overpaid_amount: 0,
|
|
76
|
+
fee_total: 0
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function incrementCounter(store, key) {
|
|
80
|
+
const normalizedKey = key.trim() || "UNKNOWN";
|
|
81
|
+
store[normalizedKey] = (store[normalizedKey] ?? 0) + 1;
|
|
82
|
+
}
|
|
83
|
+
function projectPayment(payment) {
|
|
84
|
+
const paymentId = normalizeScalarString(payment.id) || "";
|
|
85
|
+
const transactionDetails = asRecord(payment.transaction_details);
|
|
86
|
+
const payer = asRecord(payment.payer);
|
|
87
|
+
const order = asRecord(payment.order);
|
|
88
|
+
const feeDetails = asArray(payment.fee_details);
|
|
89
|
+
const currencyId = normalizeString(payment.currency_id, "UNKNOWN") || "UNKNOWN";
|
|
90
|
+
const status = normalizeString(payment.status, "UNKNOWN") || "UNKNOWN";
|
|
91
|
+
const paymentMethodId = normalizeScalarString(payment.payment_method_id) || normalizeScalarString(asRecord(payment.payment_method).id) || "UNKNOWN";
|
|
92
|
+
const paymentTypeId = normalizeString(payment.payment_type_id) || "UNKNOWN";
|
|
93
|
+
const transactionAmount = toNumber(payment.transaction_amount);
|
|
94
|
+
const totalPaidAmount = toNumber(transactionDetails.total_paid_amount ?? payment.total_paid_amount);
|
|
95
|
+
const netReceivedAmount = toNumber(transactionDetails.net_received_amount);
|
|
96
|
+
const overpaidAmount = toNumber(transactionDetails.overpaid_amount);
|
|
97
|
+
const feeTotal = roundMoney(feeDetails.reduce((accumulator, fee) => accumulator + toNumber(fee.amount), 0));
|
|
98
|
+
const dateCreated = compactDateTime(payment.date_created);
|
|
99
|
+
const dateLastUpdated = compactDateTime(payment.date_last_updated ?? payment.last_updated);
|
|
100
|
+
const description = normalizeString(payment.description);
|
|
101
|
+
const orderId = normalizeScalarString(order.id) || null;
|
|
102
|
+
const payerId = normalizeScalarString(payer.id) || null;
|
|
103
|
+
const payerEmail = normalizeString(payer.email);
|
|
104
|
+
const payerType = normalizeString(payer.type);
|
|
105
|
+
const payerFirstName = normalizeString(payer.first_name);
|
|
106
|
+
const payerLastName = normalizeString(payer.last_name);
|
|
107
|
+
const externalReference = normalizeString(transactionDetails.external_reference);
|
|
108
|
+
return {
|
|
109
|
+
row: [
|
|
110
|
+
paymentId || null,
|
|
111
|
+
normalizeString(payment.status) || null,
|
|
112
|
+
normalizeString(payment.status_detail) || null,
|
|
113
|
+
currencyId,
|
|
114
|
+
transactionAmount,
|
|
115
|
+
totalPaidAmount,
|
|
116
|
+
netReceivedAmount,
|
|
117
|
+
overpaidAmount,
|
|
118
|
+
paymentMethodId,
|
|
119
|
+
paymentTypeId,
|
|
120
|
+
toNumber(payment.installments),
|
|
121
|
+
dateCreated,
|
|
122
|
+
dateLastUpdated,
|
|
123
|
+
description || null,
|
|
124
|
+
orderId,
|
|
125
|
+
payerId,
|
|
126
|
+
payerEmail || null,
|
|
127
|
+
payerType || null,
|
|
128
|
+
payerFirstName || null,
|
|
129
|
+
payerLastName || null,
|
|
130
|
+
feeDetails.length,
|
|
131
|
+
feeTotal,
|
|
132
|
+
externalReference || null
|
|
133
|
+
],
|
|
134
|
+
feeRows: feeDetails.map((fee) => [
|
|
135
|
+
paymentId || null,
|
|
136
|
+
normalizeString(fee.type) || null,
|
|
137
|
+
toNumber(fee.amount)
|
|
138
|
+
]),
|
|
139
|
+
paymentId,
|
|
140
|
+
currencyId,
|
|
141
|
+
status,
|
|
142
|
+
paymentMethodId,
|
|
143
|
+
paymentTypeId,
|
|
144
|
+
hasOrder: Boolean(orderId),
|
|
145
|
+
hasPayer: Boolean(payerId || payerEmail),
|
|
146
|
+
feeTotal
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function buildBreakdownEntries(store) {
|
|
150
|
+
const total = Object.values(store).reduce((accumulator, value) => accumulator + value, 0);
|
|
151
|
+
return Object.entries(store).map(([key, count]) => ({
|
|
152
|
+
key,
|
|
153
|
+
count,
|
|
154
|
+
rate: total > 0 ? roundMoney(count / total) : 0
|
|
155
|
+
})).sort((left, right) => right.count - left.count || left.key.localeCompare(right.key));
|
|
156
|
+
}
|
|
157
|
+
function buildCurrencyBreakdowns(store) {
|
|
158
|
+
return Object.entries(store).map(([currencyId, totals]) => ({
|
|
159
|
+
currency_id: currencyId,
|
|
160
|
+
count: totals.count,
|
|
161
|
+
transaction_amount: roundMoney(totals.transaction_amount),
|
|
162
|
+
total_paid_amount: roundMoney(totals.total_paid_amount),
|
|
163
|
+
net_received_amount: roundMoney(totals.net_received_amount),
|
|
164
|
+
overpaid_amount: roundMoney(totals.overpaid_amount),
|
|
165
|
+
fee_total: roundMoney(totals.fee_total)
|
|
166
|
+
})).sort((left, right) => right.count - left.count || left.currency_id.localeCompare(right.currency_id));
|
|
167
|
+
}
|
|
168
|
+
function buildAlerts(params) {
|
|
169
|
+
const alerts = [];
|
|
170
|
+
if (params.failedCount > 0) {
|
|
171
|
+
alerts.push(`${params.failedCount} payment${params.failedCount === 1 ? "" : "s"} failed to fetch.`);
|
|
172
|
+
}
|
|
173
|
+
if (params.successfulCount === 0 && params.failedCount > 0) {
|
|
174
|
+
alerts.push("No payments were successfully retrieved.");
|
|
175
|
+
}
|
|
176
|
+
if (params.paymentsWithoutOrderCount > 0) {
|
|
177
|
+
alerts.push(
|
|
178
|
+
`${params.paymentsWithoutOrderCount} payment${params.paymentsWithoutOrderCount === 1 ? "" : "s"} do not include an order reference.`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (params.paymentsWithoutPayerCount > 0) {
|
|
182
|
+
alerts.push(
|
|
183
|
+
`${params.paymentsWithoutPayerCount} payment${params.paymentsWithoutPayerCount === 1 ? "" : "s"} are missing payer data.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (params.currenciesObserved.length > 1) {
|
|
187
|
+
alerts.push(`Multiple currencies detected: ${params.currenciesObserved.join(", ")}.`);
|
|
188
|
+
}
|
|
189
|
+
return alerts;
|
|
190
|
+
}
|
|
191
|
+
function buildPaymentPayload(params) {
|
|
192
|
+
const currencyTotals = {};
|
|
193
|
+
const statusCounts = {};
|
|
194
|
+
const paymentMethodCounts = {};
|
|
195
|
+
const paymentTypeCounts = {};
|
|
196
|
+
const payments = [];
|
|
197
|
+
const feeDetailRows = [];
|
|
198
|
+
let paymentsWithOrderCount = 0;
|
|
199
|
+
let paymentsWithoutOrderCount = 0;
|
|
200
|
+
let paymentsWithoutPayerCount = 0;
|
|
201
|
+
for (const projection of params.successful) {
|
|
202
|
+
payments.push(projection.row);
|
|
203
|
+
feeDetailRows.push(...projection.feeRows);
|
|
204
|
+
const currencyBucketTotals = currencyBucket(currencyTotals, projection.currencyId, createCurrencyTotals);
|
|
205
|
+
currencyBucketTotals.count += 1;
|
|
206
|
+
currencyBucketTotals.transaction_amount += projection.row[4] ? Number(projection.row[4]) : 0;
|
|
207
|
+
currencyBucketTotals.total_paid_amount += projection.row[5] ? Number(projection.row[5]) : 0;
|
|
208
|
+
currencyBucketTotals.net_received_amount += projection.row[6] ? Number(projection.row[6]) : 0;
|
|
209
|
+
currencyBucketTotals.overpaid_amount += projection.row[7] ? Number(projection.row[7]) : 0;
|
|
210
|
+
currencyBucketTotals.fee_total += projection.feeTotal;
|
|
211
|
+
incrementCounter(statusCounts, projection.status);
|
|
212
|
+
incrementCounter(paymentMethodCounts, projection.paymentMethodId);
|
|
213
|
+
incrementCounter(paymentTypeCounts, projection.paymentTypeId);
|
|
214
|
+
if (projection.hasOrder) {
|
|
215
|
+
paymentsWithOrderCount += 1;
|
|
216
|
+
} else {
|
|
217
|
+
paymentsWithoutOrderCount += 1;
|
|
218
|
+
}
|
|
219
|
+
if (!projection.hasPayer) {
|
|
220
|
+
paymentsWithoutPayerCount += 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const currenciesObserved = Object.keys(currencyTotals).sort((left, right) => left.localeCompare(right));
|
|
224
|
+
const summary = {
|
|
225
|
+
requested_count: params.requestedPaymentIds.length,
|
|
226
|
+
successful_count: params.successful.length,
|
|
227
|
+
failed_count: params.failed.length,
|
|
228
|
+
payments_with_order_count: paymentsWithOrderCount,
|
|
229
|
+
payments_without_order_count: paymentsWithoutOrderCount,
|
|
230
|
+
payments_without_payer_count: paymentsWithoutPayerCount,
|
|
231
|
+
currency_totals: Object.fromEntries(
|
|
232
|
+
Object.entries(currencyTotals).map(([currencyId, totals]) => [currencyId, stripNulls({
|
|
233
|
+
count: totals.count,
|
|
234
|
+
transaction_amount: roundMoney(totals.transaction_amount),
|
|
235
|
+
total_paid_amount: roundMoney(totals.total_paid_amount),
|
|
236
|
+
net_received_amount: roundMoney(totals.net_received_amount),
|
|
237
|
+
overpaid_amount: roundMoney(totals.overpaid_amount),
|
|
238
|
+
fee_total: roundMoney(totals.fee_total)
|
|
239
|
+
})])
|
|
240
|
+
),
|
|
241
|
+
status_counts: statusCounts,
|
|
242
|
+
payment_method_counts: paymentMethodCounts,
|
|
243
|
+
payment_type_counts: paymentTypeCounts
|
|
244
|
+
};
|
|
245
|
+
const breakdowns = stripNulls({
|
|
246
|
+
by_currency: buildCurrencyBreakdowns(currencyTotals),
|
|
247
|
+
by_status: buildBreakdownEntries(statusCounts),
|
|
248
|
+
by_payment_method: buildBreakdownEntries(paymentMethodCounts),
|
|
249
|
+
by_payment_type: buildBreakdownEntries(paymentTypeCounts)
|
|
250
|
+
});
|
|
251
|
+
const alerts = buildAlerts({
|
|
252
|
+
successfulCount: params.successful.length,
|
|
253
|
+
failedCount: params.failed.length,
|
|
254
|
+
paymentsWithoutOrderCount,
|
|
255
|
+
paymentsWithoutPayerCount,
|
|
256
|
+
currenciesObserved
|
|
257
|
+
});
|
|
258
|
+
const payload = stripNulls({
|
|
259
|
+
metadata: {
|
|
260
|
+
profile_id: params.profileId,
|
|
261
|
+
endpoint: "/v1/payments/{payment_id}",
|
|
262
|
+
mode: params.requestedPaymentIds.length === 1 ? "single" : "batch",
|
|
263
|
+
requested_count: params.requestedPaymentIds.length,
|
|
264
|
+
successful_count: params.successful.length,
|
|
265
|
+
failed_count: params.failed.length,
|
|
266
|
+
coverage_complete: params.failed.length === 0,
|
|
267
|
+
requested_payment_ids: params.requestedPaymentIds,
|
|
268
|
+
successful_payment_ids: params.successful.map((entry) => entry.paymentId),
|
|
269
|
+
failed_payment_ids: params.failed.map((entry) => entry.paymentId)
|
|
270
|
+
},
|
|
271
|
+
summary,
|
|
272
|
+
breakdowns,
|
|
273
|
+
alerts,
|
|
274
|
+
failures: params.failed
|
|
275
|
+
});
|
|
276
|
+
return {
|
|
277
|
+
...payload,
|
|
278
|
+
payments_schema: paymentsSchema,
|
|
279
|
+
payments,
|
|
280
|
+
payment_fee_details_schema: paymentFeeDetailsSchema,
|
|
281
|
+
payment_fee_details: feeDetailRows
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function meliGetPaymentDetailsHandler(params) {
|
|
285
|
+
try {
|
|
286
|
+
const profileResolution = await resolveMercadoLibreProfileOrSelection(params.profileId);
|
|
287
|
+
if (!profileResolution.ok) {
|
|
288
|
+
return profileResolution.response;
|
|
289
|
+
}
|
|
290
|
+
const profileId = profileResolution.value.profileId;
|
|
291
|
+
if (params.paymentId) {
|
|
292
|
+
const payment = await getMercadoLibrePaymentDetails(profileId, params.paymentId);
|
|
293
|
+
const projected = projectPayment(payment);
|
|
294
|
+
return object(
|
|
295
|
+
buildPaymentPayload({
|
|
296
|
+
profileId,
|
|
297
|
+
requestedPaymentIds: [params.paymentId],
|
|
298
|
+
successful: [projected],
|
|
299
|
+
failed: []
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
const batch = await getMercadoLibrePaymentDetailsBatch(profileId, params.paymentIds ?? []);
|
|
304
|
+
return object(
|
|
305
|
+
buildPaymentPayload({
|
|
306
|
+
profileId,
|
|
307
|
+
requestedPaymentIds: params.paymentIds ?? [],
|
|
308
|
+
successful: batch.successful.map((entry) => projectPayment(entry.payment)),
|
|
309
|
+
failed: batch.failed
|
|
310
|
+
})
|
|
311
|
+
);
|
|
312
|
+
} catch (err) {
|
|
313
|
+
return error(formatMercadoLibreError(err, "Failed to fetch MercadoLibre payment details"));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
export {
|
|
317
|
+
meliGetPaymentDetailsHandler,
|
|
318
|
+
meliGetPaymentDetailsSchema,
|
|
319
|
+
paymentFeeDetailsSchema,
|
|
320
|
+
paymentsSchema
|
|
321
|
+
};
|
|
322
|
+
//# sourceMappingURL=get-payment-details.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/mercadolibre/get-payment-details.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatMercadoLibreError } from \"../../services/mercadolibre/mercadolibre-api.js\";\nimport {\n getMercadoLibrePaymentDetails,\n getMercadoLibrePaymentDetailsBatch,\n} from \"../../services/mercadolibre/mercadolibre-payments.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport {\n asArray,\n asRecord,\n compactDateTime,\n currencyBucket,\n normalizeScalarString,\n normalizeString,\n roundMoney,\n toNumber,\n} from \"./helpers.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"./profile-resolution.js\";\nimport { mercadolibreProfileIdSchemaField } from \"./write-helpers.js\";\n\nconst MAX_PAYMENT_IDS = 250;\n\nconst paymentIdSchemaField = z\n .string()\n .trim()\n .min(1)\n .describe(\"MercadoLibre payment id to inspect.\");\n\nexport const meliGetPaymentDetailsSchema = z\n .object({\n profileId: mercadolibreProfileIdSchemaField,\n paymentId: paymentIdSchemaField.optional().describe(\"Single MercadoLibre payment id to inspect.\"),\n paymentIds: z\n .array(paymentIdSchemaField)\n .min(1)\n .max(MAX_PAYMENT_IDS)\n .describe(\"One or more MercadoLibre payment ids to inspect in parallel (up to 250, processed in chunks of 50).\")\n .optional(),\n })\n .superRefine((value, ctx) => {\n const hasPaymentId = Boolean(value.paymentId);\n const hasPaymentIds = Boolean(value.paymentIds?.length);\n\n if (hasPaymentId === hasPaymentIds) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"Provide exactly one of paymentId or paymentIds.\",\n path: [\"paymentId\"],\n });\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"Provide exactly one of paymentId or paymentIds.\",\n path: [\"paymentIds\"],\n });\n }\n });\n\nexport const paymentsSchema = [\n \"payment_id\",\n \"status\",\n \"status_detail\",\n \"currency_id\",\n \"transaction_amount\",\n \"total_paid_amount\",\n \"net_received_amount\",\n \"overpaid_amount\",\n \"payment_method_id\",\n \"payment_type_id\",\n \"installments\",\n \"date_created\",\n \"date_last_updated\",\n \"description\",\n \"order_id\",\n \"payer_id\",\n \"payer_email\",\n \"payer_type\",\n \"payer_first_name\",\n \"payer_last_name\",\n \"fee_count\",\n \"fee_total\",\n \"external_reference\",\n] as const;\n\nexport const paymentFeeDetailsSchema = [\"payment_id\", \"fee_type\", \"fee_amount\"] as const;\n\ntype PaymentRow = (string | number | null)[];\ntype FeeRow = (string | number | null)[];\n\ntype PaymentProjection = {\n row: PaymentRow;\n feeRows: FeeRow[];\n paymentId: string;\n currencyId: string;\n status: string;\n paymentMethodId: string;\n paymentTypeId: string;\n hasOrder: boolean;\n hasPayer: boolean;\n feeTotal: number;\n};\n\ntype CurrencyTotals = {\n count: number;\n transaction_amount: number;\n total_paid_amount: number;\n net_received_amount: number;\n overpaid_amount: number;\n fee_total: number;\n};\n\nfunction createCurrencyTotals(): CurrencyTotals {\n return {\n count: 0,\n transaction_amount: 0,\n total_paid_amount: 0,\n net_received_amount: 0,\n overpaid_amount: 0,\n fee_total: 0,\n };\n}\n\nfunction incrementCounter(store: Record<string, number>, key: string): void {\n const normalizedKey = key.trim() || \"UNKNOWN\";\n store[normalizedKey] = (store[normalizedKey] ?? 0) + 1;\n}\n\nfunction projectPayment(payment: Record<string, unknown>): PaymentProjection {\n const paymentId = normalizeScalarString(payment.id) || \"\";\n const transactionDetails = asRecord(payment.transaction_details);\n const payer = asRecord(payment.payer);\n const order = asRecord(payment.order);\n const feeDetails = asArray<Record<string, unknown>>(payment.fee_details);\n const currencyId = normalizeString(payment.currency_id, \"UNKNOWN\") || \"UNKNOWN\";\n const status = normalizeString(payment.status, \"UNKNOWN\") || \"UNKNOWN\";\n const paymentMethodId =\n normalizeScalarString(payment.payment_method_id) || normalizeScalarString(asRecord(payment.payment_method).id) || \"UNKNOWN\";\n const paymentTypeId = normalizeString(payment.payment_type_id) || \"UNKNOWN\";\n const transactionAmount = toNumber(payment.transaction_amount);\n const totalPaidAmount = toNumber(transactionDetails.total_paid_amount ?? payment.total_paid_amount);\n const netReceivedAmount = toNumber(transactionDetails.net_received_amount);\n const overpaidAmount = toNumber(transactionDetails.overpaid_amount);\n const feeTotal = roundMoney(feeDetails.reduce((accumulator, fee) => accumulator + toNumber(fee.amount), 0));\n const dateCreated = compactDateTime(payment.date_created);\n const dateLastUpdated = compactDateTime(payment.date_last_updated ?? payment.last_updated);\n const description = normalizeString(payment.description);\n const orderId = normalizeScalarString(order.id) || null;\n const payerId = normalizeScalarString(payer.id) || null;\n const payerEmail = normalizeString(payer.email);\n const payerType = normalizeString(payer.type);\n const payerFirstName = normalizeString(payer.first_name);\n const payerLastName = normalizeString(payer.last_name);\n const externalReference = normalizeString(transactionDetails.external_reference);\n\n return {\n row: [\n paymentId || null,\n normalizeString(payment.status) || null,\n normalizeString(payment.status_detail) || null,\n currencyId,\n transactionAmount,\n totalPaidAmount,\n netReceivedAmount,\n overpaidAmount,\n paymentMethodId,\n paymentTypeId,\n toNumber(payment.installments),\n dateCreated,\n dateLastUpdated,\n description || null,\n orderId,\n payerId,\n payerEmail || null,\n payerType || null,\n payerFirstName || null,\n payerLastName || null,\n feeDetails.length,\n feeTotal,\n externalReference || null,\n ],\n feeRows: feeDetails.map((fee) => [\n paymentId || null,\n normalizeString(fee.type) || null,\n toNumber(fee.amount),\n ]),\n paymentId,\n currencyId,\n status,\n paymentMethodId,\n paymentTypeId,\n hasOrder: Boolean(orderId),\n hasPayer: Boolean(payerId || payerEmail),\n feeTotal,\n };\n}\n\nfunction buildBreakdownEntries(store: Record<string, number>) {\n const total = Object.values(store).reduce((accumulator, value) => accumulator + value, 0);\n\n return Object.entries(store)\n .map(([key, count]) => ({\n key,\n count,\n rate: total > 0 ? roundMoney(count / total) : 0,\n }))\n .sort((left, right) => right.count - left.count || left.key.localeCompare(right.key));\n}\n\nfunction buildCurrencyBreakdowns(store: Record<string, CurrencyTotals>) {\n return Object.entries(store)\n .map(([currencyId, totals]) => ({\n currency_id: currencyId,\n count: totals.count,\n transaction_amount: roundMoney(totals.transaction_amount),\n total_paid_amount: roundMoney(totals.total_paid_amount),\n net_received_amount: roundMoney(totals.net_received_amount),\n overpaid_amount: roundMoney(totals.overpaid_amount),\n fee_total: roundMoney(totals.fee_total),\n }))\n .sort((left, right) => right.count - left.count || left.currency_id.localeCompare(right.currency_id));\n}\n\nfunction buildAlerts(params: {\n successfulCount: number;\n failedCount: number;\n paymentsWithoutOrderCount: number;\n paymentsWithoutPayerCount: number;\n currenciesObserved: string[];\n}): string[] {\n const alerts: string[] = [];\n\n if (params.failedCount > 0) {\n alerts.push(`${params.failedCount} payment${params.failedCount === 1 ? \"\" : \"s\"} failed to fetch.`);\n }\n\n if (params.successfulCount === 0 && params.failedCount > 0) {\n alerts.push(\"No payments were successfully retrieved.\");\n }\n\n if (params.paymentsWithoutOrderCount > 0) {\n alerts.push(\n `${params.paymentsWithoutOrderCount} payment${params.paymentsWithoutOrderCount === 1 ? \"\" : \"s\"} do not include an order reference.`\n );\n }\n\n if (params.paymentsWithoutPayerCount > 0) {\n alerts.push(\n `${params.paymentsWithoutPayerCount} payment${params.paymentsWithoutPayerCount === 1 ? \"\" : \"s\"} are missing payer data.`\n );\n }\n\n if (params.currenciesObserved.length > 1) {\n alerts.push(`Multiple currencies detected: ${params.currenciesObserved.join(\", \")}.`);\n }\n\n return alerts;\n}\n\nfunction buildPaymentPayload(params: {\n profileId: string;\n requestedPaymentIds: string[];\n successful: PaymentProjection[];\n failed: Array<{\n paymentId: string;\n message: string;\n statusCode?: number;\n attempts: number;\n retryable: boolean;\n }>;\n}) {\n const currencyTotals: Record<string, CurrencyTotals> = {};\n const statusCounts: Record<string, number> = {};\n const paymentMethodCounts: Record<string, number> = {};\n const paymentTypeCounts: Record<string, number> = {};\n const payments: PaymentRow[] = [];\n const feeDetailRows: FeeRow[] = [];\n let paymentsWithOrderCount = 0;\n let paymentsWithoutOrderCount = 0;\n let paymentsWithoutPayerCount = 0;\n\n for (const projection of params.successful) {\n payments.push(projection.row);\n feeDetailRows.push(...projection.feeRows);\n\n const currencyBucketTotals = currencyBucket(currencyTotals, projection.currencyId, createCurrencyTotals);\n currencyBucketTotals.count += 1;\n currencyBucketTotals.transaction_amount += projection.row[4] ? Number(projection.row[4]) : 0;\n currencyBucketTotals.total_paid_amount += projection.row[5] ? Number(projection.row[5]) : 0;\n currencyBucketTotals.net_received_amount += projection.row[6] ? Number(projection.row[6]) : 0;\n currencyBucketTotals.overpaid_amount += projection.row[7] ? Number(projection.row[7]) : 0;\n currencyBucketTotals.fee_total += projection.feeTotal;\n\n incrementCounter(statusCounts, projection.status);\n incrementCounter(paymentMethodCounts, projection.paymentMethodId);\n incrementCounter(paymentTypeCounts, projection.paymentTypeId);\n\n if (projection.hasOrder) {\n paymentsWithOrderCount += 1;\n } else {\n paymentsWithoutOrderCount += 1;\n }\n\n if (!projection.hasPayer) {\n paymentsWithoutPayerCount += 1;\n }\n }\n\n const currenciesObserved = Object.keys(currencyTotals).sort((left, right) => left.localeCompare(right));\n const summary = {\n requested_count: params.requestedPaymentIds.length,\n successful_count: params.successful.length,\n failed_count: params.failed.length,\n payments_with_order_count: paymentsWithOrderCount,\n payments_without_order_count: paymentsWithoutOrderCount,\n payments_without_payer_count: paymentsWithoutPayerCount,\n currency_totals: Object.fromEntries(\n Object.entries(currencyTotals).map(([currencyId, totals]) => [currencyId, stripNulls({\n count: totals.count,\n transaction_amount: roundMoney(totals.transaction_amount),\n total_paid_amount: roundMoney(totals.total_paid_amount),\n net_received_amount: roundMoney(totals.net_received_amount),\n overpaid_amount: roundMoney(totals.overpaid_amount),\n fee_total: roundMoney(totals.fee_total),\n })])\n ),\n status_counts: statusCounts,\n payment_method_counts: paymentMethodCounts,\n payment_type_counts: paymentTypeCounts,\n };\n\n const breakdowns = stripNulls({\n by_currency: buildCurrencyBreakdowns(currencyTotals),\n by_status: buildBreakdownEntries(statusCounts),\n by_payment_method: buildBreakdownEntries(paymentMethodCounts),\n by_payment_type: buildBreakdownEntries(paymentTypeCounts),\n });\n\n const alerts = buildAlerts({\n successfulCount: params.successful.length,\n failedCount: params.failed.length,\n paymentsWithoutOrderCount,\n paymentsWithoutPayerCount,\n currenciesObserved,\n });\n\n const payload = stripNulls({\n metadata: {\n profile_id: params.profileId,\n endpoint: \"/v1/payments/{payment_id}\",\n mode: params.requestedPaymentIds.length === 1 ? \"single\" : \"batch\",\n requested_count: params.requestedPaymentIds.length,\n successful_count: params.successful.length,\n failed_count: params.failed.length,\n coverage_complete: params.failed.length === 0,\n requested_payment_ids: params.requestedPaymentIds,\n successful_payment_ids: params.successful.map((entry) => entry.paymentId),\n failed_payment_ids: params.failed.map((entry) => entry.paymentId),\n },\n summary,\n breakdowns,\n alerts,\n failures: params.failed,\n });\n\n // Attach compact positional blocks after stripping nullish metadata so row length stays aligned.\n return {\n ...payload,\n payments_schema: paymentsSchema,\n payments,\n payment_fee_details_schema: paymentFeeDetailsSchema,\n payment_fee_details: feeDetailRows,\n };\n}\n\nexport async function meliGetPaymentDetailsHandler(\n params: z.infer<typeof meliGetPaymentDetailsSchema>\n) {\n try {\n const profileResolution = await resolveMercadoLibreProfileOrSelection(params.profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const profileId = profileResolution.value.profileId;\n\n if (params.paymentId) {\n const payment = await getMercadoLibrePaymentDetails(profileId, params.paymentId);\n const projected = projectPayment(payment);\n\n return object(\n buildPaymentPayload({\n profileId,\n requestedPaymentIds: [params.paymentId],\n successful: [projected],\n failed: [],\n })\n );\n }\n\n const batch = await getMercadoLibrePaymentDetailsBatch(profileId, params.paymentIds ?? []);\n\n return object(\n buildPaymentPayload({\n profileId,\n requestedPaymentIds: params.paymentIds ?? [],\n successful: batch.successful.map((entry) => projectPayment(entry.payment)),\n failed: batch.failed,\n })\n );\n } catch (err) {\n return error(formatMercadoLibreError(err, \"Failed to fetch MercadoLibre payment details\"));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,6CAA6C;AACtD,SAAS,wCAAwC;AAEjD,MAAM,kBAAkB;AAExB,MAAM,uBAAuB,EAC1B,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,qCAAqC;AAE1C,MAAM,8BAA8B,EACxC,OAAO;AAAA,EACN,WAAW;AAAA,EACX,WAAW,qBAAqB,SAAS,EAAE,SAAS,4CAA4C;AAAA,EAChG,YAAY,EACT,MAAM,oBAAoB,EAC1B,IAAI,CAAC,EACL,IAAI,eAAe,EACnB,SAAS,qGAAqG,EAC9G,SAAS;AACd,CAAC,EACA,YAAY,CAAC,OAAO,QAAQ;AAC3B,QAAM,eAAe,QAAQ,MAAM,SAAS;AAC5C,QAAM,gBAAgB,QAAQ,MAAM,YAAY,MAAM;AAEtD,MAAI,iBAAiB,eAAe;AAClC,QAAI,SAAS;AAAA,MACX,MAAM,EAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,WAAW;AAAA,IACpB,CAAC;AACD,QAAI,SAAS;AAAA,MACX,MAAM,EAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,YAAY;AAAA,IACrB,CAAC;AAAA,EACH;AACF,CAAC;AAEI,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,0BAA0B,CAAC,cAAc,YAAY,YAAY;AA2B9E,SAAS,uBAAuC;AAC9C,SAAO;AAAA,IACL,OAAO;AAAA,IACP,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,WAAW;AAAA,EACb;AACF;AAEA,SAAS,iBAAiB,OAA+B,KAAmB;AAC1E,QAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,QAAM,aAAa,KAAK,MAAM,aAAa,KAAK,KAAK;AACvD;AAEA,SAAS,eAAe,SAAqD;AAC3E,QAAM,YAAY,sBAAsB,QAAQ,EAAE,KAAK;AACvD,QAAM,qBAAqB,SAAS,QAAQ,mBAAmB;AAC/D,QAAM,QAAQ,SAAS,QAAQ,KAAK;AACpC,QAAM,QAAQ,SAAS,QAAQ,KAAK;AACpC,QAAM,aAAa,QAAiC,QAAQ,WAAW;AACvE,QAAM,aAAa,gBAAgB,QAAQ,aAAa,SAAS,KAAK;AACtE,QAAM,SAAS,gBAAgB,QAAQ,QAAQ,SAAS,KAAK;AAC7D,QAAM,kBACJ,sBAAsB,QAAQ,iBAAiB,KAAK,sBAAsB,SAAS,QAAQ,cAAc,EAAE,EAAE,KAAK;AACpH,QAAM,gBAAgB,gBAAgB,QAAQ,eAAe,KAAK;AAClE,QAAM,oBAAoB,SAAS,QAAQ,kBAAkB;AAC7D,QAAM,kBAAkB,SAAS,mBAAmB,qBAAqB,QAAQ,iBAAiB;AAClG,QAAM,oBAAoB,SAAS,mBAAmB,mBAAmB;AACzE,QAAM,iBAAiB,SAAS,mBAAmB,eAAe;AAClE,QAAM,WAAW,WAAW,WAAW,OAAO,CAAC,aAAa,QAAQ,cAAc,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC;AAC1G,QAAM,cAAc,gBAAgB,QAAQ,YAAY;AACxD,QAAM,kBAAkB,gBAAgB,QAAQ,qBAAqB,QAAQ,YAAY;AACzF,QAAM,cAAc,gBAAgB,QAAQ,WAAW;AACvD,QAAM,UAAU,sBAAsB,MAAM,EAAE,KAAK;AACnD,QAAM,UAAU,sBAAsB,MAAM,EAAE,KAAK;AACnD,QAAM,aAAa,gBAAgB,MAAM,KAAK;AAC9C,QAAM,YAAY,gBAAgB,MAAM,IAAI;AAC5C,QAAM,iBAAiB,gBAAgB,MAAM,UAAU;AACvD,QAAM,gBAAgB,gBAAgB,MAAM,SAAS;AACrD,QAAM,oBAAoB,gBAAgB,mBAAmB,kBAAkB;AAE/E,SAAO;AAAA,IACL,KAAK;AAAA,MACH,aAAa;AAAA,MACb,gBAAgB,QAAQ,MAAM,KAAK;AAAA,MACnC,gBAAgB,QAAQ,aAAa,KAAK;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,QAAQ,YAAY;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,iBAAiB;AAAA,MACjB,WAAW;AAAA,MACX;AAAA,MACA,qBAAqB;AAAA,IACvB;AAAA,IACA,SAAS,WAAW,IAAI,CAAC,QAAQ;AAAA,MAC/B,aAAa;AAAA,MACb,gBAAgB,IAAI,IAAI,KAAK;AAAA,MAC7B,SAAS,IAAI,MAAM;AAAA,IACrB,CAAC;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,QAAQ,OAAO;AAAA,IACzB,UAAU,QAAQ,WAAW,UAAU;AAAA,IACvC;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,OAA+B;AAC5D,QAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,OAAO,CAAC,aAAa,UAAU,cAAc,OAAO,CAAC;AAExF,SAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,IACtB;AAAA,IACA;AAAA,IACA,MAAM,QAAQ,IAAI,WAAW,QAAQ,KAAK,IAAI;AAAA,EAChD,EAAE,EACD,KAAK,CAAC,MAAM,UAAU,MAAM,QAAQ,KAAK,SAAS,KAAK,IAAI,cAAc,MAAM,GAAG,CAAC;AACxF;AAEA,SAAS,wBAAwB,OAAuC;AACtE,SAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,YAAY,MAAM,OAAO;AAAA,IAC9B,aAAa;AAAA,IACb,OAAO,OAAO;AAAA,IACd,oBAAoB,WAAW,OAAO,kBAAkB;AAAA,IACxD,mBAAmB,WAAW,OAAO,iBAAiB;AAAA,IACtD,qBAAqB,WAAW,OAAO,mBAAmB;AAAA,IAC1D,iBAAiB,WAAW,OAAO,eAAe;AAAA,IAClD,WAAW,WAAW,OAAO,SAAS;AAAA,EACxC,EAAE,EACD,KAAK,CAAC,MAAM,UAAU,MAAM,QAAQ,KAAK,SAAS,KAAK,YAAY,cAAc,MAAM,WAAW,CAAC;AACxG;AAEA,SAAS,YAAY,QAMR;AACX,QAAM,SAAmB,CAAC;AAE1B,MAAI,OAAO,cAAc,GAAG;AAC1B,WAAO,KAAK,GAAG,OAAO,WAAW,WAAW,OAAO,gBAAgB,IAAI,KAAK,GAAG,mBAAmB;AAAA,EACpG;AAEA,MAAI,OAAO,oBAAoB,KAAK,OAAO,cAAc,GAAG;AAC1D,WAAO,KAAK,0CAA0C;AAAA,EACxD;AAEA,MAAI,OAAO,4BAA4B,GAAG;AACxC,WAAO;AAAA,MACL,GAAG,OAAO,yBAAyB,WAAW,OAAO,8BAA8B,IAAI,KAAK,GAAG;AAAA,IACjG;AAAA,EACF;AAEA,MAAI,OAAO,4BAA4B,GAAG;AACxC,WAAO;AAAA,MACL,GAAG,OAAO,yBAAyB,WAAW,OAAO,8BAA8B,IAAI,KAAK,GAAG;AAAA,IACjG;AAAA,EACF;AAEA,MAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,WAAO,KAAK,iCAAiC,OAAO,mBAAmB,KAAK,IAAI,CAAC,GAAG;AAAA,EACtF;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,QAW1B;AACD,QAAM,iBAAiD,CAAC;AACxD,QAAM,eAAuC,CAAC;AAC9C,QAAM,sBAA8C,CAAC;AACrD,QAAM,oBAA4C,CAAC;AACnD,QAAM,WAAyB,CAAC;AAChC,QAAM,gBAA0B,CAAC;AACjC,MAAI,yBAAyB;AAC7B,MAAI,4BAA4B;AAChC,MAAI,4BAA4B;AAEhC,aAAW,cAAc,OAAO,YAAY;AAC1C,aAAS,KAAK,WAAW,GAAG;AAC5B,kBAAc,KAAK,GAAG,WAAW,OAAO;AAExC,UAAM,uBAAuB,eAAe,gBAAgB,WAAW,YAAY,oBAAoB;AACvG,yBAAqB,SAAS;AAC9B,yBAAqB,sBAAsB,WAAW,IAAI,CAAC,IAAI,OAAO,WAAW,IAAI,CAAC,CAAC,IAAI;AAC3F,yBAAqB,qBAAqB,WAAW,IAAI,CAAC,IAAI,OAAO,WAAW,IAAI,CAAC,CAAC,IAAI;AAC1F,yBAAqB,uBAAuB,WAAW,IAAI,CAAC,IAAI,OAAO,WAAW,IAAI,CAAC,CAAC,IAAI;AAC5F,yBAAqB,mBAAmB,WAAW,IAAI,CAAC,IAAI,OAAO,WAAW,IAAI,CAAC,CAAC,IAAI;AACxF,yBAAqB,aAAa,WAAW;AAE7C,qBAAiB,cAAc,WAAW,MAAM;AAChD,qBAAiB,qBAAqB,WAAW,eAAe;AAChE,qBAAiB,mBAAmB,WAAW,aAAa;AAE5D,QAAI,WAAW,UAAU;AACvB,gCAA0B;AAAA,IAC5B,OAAO;AACL,mCAA6B;AAAA,IAC/B;AAEA,QAAI,CAAC,WAAW,UAAU;AACxB,mCAA6B;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,qBAAqB,OAAO,KAAK,cAAc,EAAE,KAAK,CAAC,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC;AACtG,QAAM,UAAU;AAAA,IACd,iBAAiB,OAAO,oBAAoB;AAAA,IAC5C,kBAAkB,OAAO,WAAW;AAAA,IACpC,cAAc,OAAO,OAAO;AAAA,IAC5B,2BAA2B;AAAA,IAC3B,8BAA8B;AAAA,IAC9B,8BAA8B;AAAA,IAC9B,iBAAiB,OAAO;AAAA,MACtB,OAAO,QAAQ,cAAc,EAAE,IAAI,CAAC,CAAC,YAAY,MAAM,MAAM,CAAC,YAAY,WAAW;AAAA,QACnF,OAAO,OAAO;AAAA,QACd,oBAAoB,WAAW,OAAO,kBAAkB;AAAA,QACxD,mBAAmB,WAAW,OAAO,iBAAiB;AAAA,QACtD,qBAAqB,WAAW,OAAO,mBAAmB;AAAA,QAC1D,iBAAiB,WAAW,OAAO,eAAe;AAAA,QAClD,WAAW,WAAW,OAAO,SAAS;AAAA,MACxC,CAAC,CAAC,CAAC;AAAA,IACL;AAAA,IACA,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,EACvB;AAEA,QAAM,aAAa,WAAW;AAAA,IAC5B,aAAa,wBAAwB,cAAc;AAAA,IACnD,WAAW,sBAAsB,YAAY;AAAA,IAC7C,mBAAmB,sBAAsB,mBAAmB;AAAA,IAC5D,iBAAiB,sBAAsB,iBAAiB;AAAA,EAC1D,CAAC;AAED,QAAM,SAAS,YAAY;AAAA,IACzB,iBAAiB,OAAO,WAAW;AAAA,IACnC,aAAa,OAAO,OAAO;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,UAAU,WAAW;AAAA,IACzB,UAAU;AAAA,MACR,YAAY,OAAO;AAAA,MACnB,UAAU;AAAA,MACV,MAAM,OAAO,oBAAoB,WAAW,IAAI,WAAW;AAAA,MAC3D,iBAAiB,OAAO,oBAAoB;AAAA,MAC5C,kBAAkB,OAAO,WAAW;AAAA,MACpC,cAAc,OAAO,OAAO;AAAA,MAC5B,mBAAmB,OAAO,OAAO,WAAW;AAAA,MAC5C,uBAAuB,OAAO;AAAA,MAC9B,wBAAwB,OAAO,WAAW,IAAI,CAAC,UAAU,MAAM,SAAS;AAAA,MACxE,oBAAoB,OAAO,OAAO,IAAI,CAAC,UAAU,MAAM,SAAS;AAAA,IAClE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,OAAO;AAAA,EACnB,CAAC;AAGD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iBAAiB;AAAA,IACjB;AAAA,IACA,4BAA4B;AAAA,IAC5B,qBAAqB;AAAA,EACvB;AACF;AAEA,eAAsB,6BACpB,QACA;AACA,MAAI;AACF,UAAM,oBAAoB,MAAM,sCAAsC,OAAO,SAAS;AACtF,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,YAAY,kBAAkB,MAAM;AAE1C,QAAI,OAAO,WAAW;AACpB,YAAM,UAAU,MAAM,8BAA8B,WAAW,OAAO,SAAS;AAC/E,YAAM,YAAY,eAAe,OAAO;AAExC,aAAO;AAAA,QACL,oBAAoB;AAAA,UAClB;AAAA,UACA,qBAAqB,CAAC,OAAO,SAAS;AAAA,UACtC,YAAY,CAAC,SAAS;AAAA,UACtB,QAAQ,CAAC;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,mCAAmC,WAAW,OAAO,cAAc,CAAC,CAAC;AAEzF,WAAO;AAAA,MACL,oBAAoB;AAAA,QAClB;AAAA,QACA,qBAAqB,OAAO,cAAc,CAAC;AAAA,QAC3C,YAAY,MAAM,WAAW,IAAI,CAAC,UAAU,eAAe,MAAM,OAAO,CAAC;AAAA,QACzE,QAAQ,MAAM;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,wBAAwB,KAAK,8CAA8C,CAAC;AAAA,EAC3F;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -2,6 +2,7 @@ export * from "./get-account-context.js";
|
|
|
2
2
|
export * from "./validate-connection.js";
|
|
3
3
|
export * from "./get-orders-summary.js";
|
|
4
4
|
export * from "./get-order-details.js";
|
|
5
|
+
export * from "./get-payment-details.js";
|
|
5
6
|
export * from "./get-sales-by-item.js";
|
|
6
7
|
export * from "./get-sales-trend.js";
|
|
7
8
|
export * from "./get-shipping-summary.js";
|
|
@@ -24,4 +25,23 @@ export * from "./answer-question.js";
|
|
|
24
25
|
export * from "./profile-resolution.js";
|
|
25
26
|
export * from "./get-site-categories-and-listing-types.js";
|
|
26
27
|
export * from "./get-billing-provisions-summary.js";
|
|
28
|
+
import {
|
|
29
|
+
meliGetBillingProvisionsByOrderHandler,
|
|
30
|
+
meliGetBillingProvisionsByOrderSchema,
|
|
31
|
+
ordersSchema,
|
|
32
|
+
paymentInfoSchema,
|
|
33
|
+
detailsSchema,
|
|
34
|
+
detailsSalesSchema,
|
|
35
|
+
detailsItemsSchema
|
|
36
|
+
} from "./get-billing-provisions-by-order.js";
|
|
37
|
+
export * from "./get-full-storage-charges.js";
|
|
38
|
+
export {
|
|
39
|
+
detailsItemsSchema as billingProvisionsByOrderDetailsItemsSchema,
|
|
40
|
+
detailsSalesSchema as billingProvisionsByOrderDetailsSalesSchema,
|
|
41
|
+
detailsSchema as billingProvisionsByOrderDetailsSchema,
|
|
42
|
+
meliGetBillingProvisionsByOrderHandler,
|
|
43
|
+
meliGetBillingProvisionsByOrderSchema,
|
|
44
|
+
ordersSchema,
|
|
45
|
+
paymentInfoSchema
|
|
46
|
+
};
|
|
27
47
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/mercadolibre/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from \"./get-account-context.js\";\nexport * from \"./validate-connection.js\";\nexport * from \"./get-orders-summary.js\";\nexport * from \"./get-order-details.js\";\nexport * from \"./get-sales-by-item.js\";\nexport * from \"./get-sales-trend.js\";\nexport * from \"./get-shipping-summary.js\";\nexport * from \"./get-item-visits.js\";\nexport * from \"./get-store-performance.js\";\nexport * from \"./search-items.js\";\nexport * from \"./get-item-details.js\";\nexport * from \"./get-listing-quality.js\";\nexport * from \"./predict-category.js\";\nexport * from \"./get-category-requirements.js\";\nexport * from \"./estimate-listing-fee.js\";\nexport * from \"./estimate-product-profitability.js\";\nexport * from \"./create-item.js\";\nexport * from \"./update-item-basic-fields.js\";\nexport * from \"./update-item-description.js\";\nexport * from \"./update-item-pictures.js\";\nexport * from \"./pause-or-reactivate-item.js\";\nexport * from \"./search-questions.js\";\nexport * from \"./answer-question.js\";\nexport * from \"./profile-resolution.js\";\nexport * from \"./get-site-categories-and-listing-types.js\";\nexport * from \"./get-billing-provisions-summary.js\";\n"],
|
|
5
|
-
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"sourcesContent": ["export * from \"./get-account-context.js\";\nexport * from \"./validate-connection.js\";\nexport * from \"./get-orders-summary.js\";\nexport * from \"./get-order-details.js\";\nexport * from \"./get-payment-details.js\";\nexport * from \"./get-sales-by-item.js\";\nexport * from \"./get-sales-trend.js\";\nexport * from \"./get-shipping-summary.js\";\nexport * from \"./get-item-visits.js\";\nexport * from \"./get-store-performance.js\";\nexport * from \"./search-items.js\";\nexport * from \"./get-item-details.js\";\nexport * from \"./get-listing-quality.js\";\nexport * from \"./predict-category.js\";\nexport * from \"./get-category-requirements.js\";\nexport * from \"./estimate-listing-fee.js\";\nexport * from \"./estimate-product-profitability.js\";\nexport * from \"./create-item.js\";\nexport * from \"./update-item-basic-fields.js\";\nexport * from \"./update-item-description.js\";\nexport * from \"./update-item-pictures.js\";\nexport * from \"./pause-or-reactivate-item.js\";\nexport * from \"./search-questions.js\";\nexport * from \"./answer-question.js\";\nexport * from \"./profile-resolution.js\";\nexport * from \"./get-site-categories-and-listing-types.js\";\nexport * from \"./get-billing-provisions-summary.js\";\nexport {\n meliGetBillingProvisionsByOrderHandler,\n meliGetBillingProvisionsByOrderSchema,\n ordersSchema,\n paymentInfoSchema,\n detailsSchema as billingProvisionsByOrderDetailsSchema,\n detailsSalesSchema as billingProvisionsByOrderDetailsSalesSchema,\n detailsItemsSchema as billingProvisionsByOrderDetailsItemsSchema,\n} from \"./get-billing-provisions-by-order.js\";\nexport * from \"./get-full-storage-charges.js\";\n"],
|
|
5
|
+
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACiB;AAAA,EACK;AAAA,EACA;AAAA,OACjB;AACP,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -30,8 +30,18 @@ vi.mock("../../src/tools/mercadolibre/profile-resolution.js", () => ({
|
|
|
30
30
|
import {
|
|
31
31
|
getMercadoLibreBillingProvisionPage,
|
|
32
32
|
getMercadoLibreBillingProvisions,
|
|
33
|
+
getMercadoLibreBillingProvisionsByOrder,
|
|
33
34
|
scopeToGroupPath
|
|
34
35
|
} from "../../src/services/mercadolibre/mercadolibre-billing.js";
|
|
36
|
+
import {
|
|
37
|
+
meliGetBillingProvisionsByOrderHandler,
|
|
38
|
+
meliGetBillingProvisionsByOrderSchema,
|
|
39
|
+
ordersSchema,
|
|
40
|
+
paymentInfoSchema,
|
|
41
|
+
detailsSchema as byOrderDetailsSchema,
|
|
42
|
+
detailsSalesSchema as byOrderDetailsSalesSchema,
|
|
43
|
+
detailsItemsSchema as byOrderDetailsItemsSchema
|
|
44
|
+
} from "../../src/tools/mercadolibre/get-billing-provisions-by-order.js";
|
|
35
45
|
import {
|
|
36
46
|
meliGetBillingProvisionsSummaryHandler,
|
|
37
47
|
meliGetBillingProvisionsSummarySchema,
|
|
@@ -145,6 +155,7 @@ describe("getMercadoLibreBillingProvisionPage", () => {
|
|
|
145
155
|
expect(p.marketplace_type).toBe("classic");
|
|
146
156
|
expect(p.order_ids).toBe("O1");
|
|
147
157
|
expect(p.item_ids).toBe("I1");
|
|
158
|
+
expect(p.site_id).toBeUndefined();
|
|
148
159
|
});
|
|
149
160
|
it("reads flat total/limit from real MELI envelope (no paging nesting)", async () => {
|
|
150
161
|
axiosGetMock.mockResolvedValue({
|
|
@@ -235,6 +246,171 @@ describe("getMercadoLibreBillingProvisions", () => {
|
|
|
235
246
|
expect(result.coverage_complete).toBe(true);
|
|
236
247
|
});
|
|
237
248
|
});
|
|
249
|
+
describe("meliGetBillingProvisionsByOrderHandler", () => {
|
|
250
|
+
beforeEach(() => {
|
|
251
|
+
vi.clearAllMocks();
|
|
252
|
+
vi.mocked(resolveProfileMock).mockResolvedValue({
|
|
253
|
+
ok: true,
|
|
254
|
+
value: { profileId: "meli-profile-1" }
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
it("requires profileId and at least one orderId", () => {
|
|
258
|
+
expect(
|
|
259
|
+
() => meliGetBillingProvisionsByOrderSchema.parse({ orderIds: ["O1"] })
|
|
260
|
+
).toThrow();
|
|
261
|
+
expect(
|
|
262
|
+
() => meliGetBillingProvisionsByOrderSchema.parse({ profileId: "profile-1", orderIds: ["O1"] })
|
|
263
|
+
).not.toThrow();
|
|
264
|
+
});
|
|
265
|
+
function officialOrderRow(overrides = {}) {
|
|
266
|
+
const paymentInfo = overrides.payment_info ?? {};
|
|
267
|
+
const details = overrides.details;
|
|
268
|
+
return {
|
|
269
|
+
order_id: overrides.order_id ?? `ORD-${Math.random().toString(36).slice(2, 8)}`,
|
|
270
|
+
sale_fee: overrides.sale_fee ?? 12.34,
|
|
271
|
+
document_id: overrides.document_id ?? "DOC-1",
|
|
272
|
+
currency_id: overrides.currency_id ?? "ARS",
|
|
273
|
+
marketplace: overrides.marketplace ?? "MELI",
|
|
274
|
+
payment_info: {
|
|
275
|
+
payment_id: paymentInfo.payment_id ?? "PAY-1",
|
|
276
|
+
payment_type: paymentInfo.payment_type ?? "credit_card",
|
|
277
|
+
payment_method_id: paymentInfo.payment_method_id ?? "visa",
|
|
278
|
+
installments: paymentInfo.installments ?? 1,
|
|
279
|
+
transaction_amount: paymentInfo.transaction_amount ?? 100,
|
|
280
|
+
total_paid_amount: paymentInfo.total_paid_amount ?? 100,
|
|
281
|
+
shipping_cost: paymentInfo.shipping_cost ?? 0,
|
|
282
|
+
coupon_amount: paymentInfo.coupon_amount ?? 0,
|
|
283
|
+
status: paymentInfo.status ?? "approved",
|
|
284
|
+
status_detail: paymentInfo.status_detail ?? "accredited",
|
|
285
|
+
...paymentInfo
|
|
286
|
+
},
|
|
287
|
+
details: details ?? [
|
|
288
|
+
{
|
|
289
|
+
detail_id: "detail-1",
|
|
290
|
+
detail_type: "sale",
|
|
291
|
+
detail_sub_type: "sale",
|
|
292
|
+
transaction_detail: "Cargo por vender",
|
|
293
|
+
detail_amount: 12.34,
|
|
294
|
+
currency_id: "ARS",
|
|
295
|
+
concept_type: "sale",
|
|
296
|
+
operation_id: "OP-1",
|
|
297
|
+
shipping_id: "SHIP-1",
|
|
298
|
+
pack_id: "PACK-1",
|
|
299
|
+
inventory_id: "INV-1",
|
|
300
|
+
sales_info: [
|
|
301
|
+
{
|
|
302
|
+
order_id: overrides.order_id ?? "ORD-1",
|
|
303
|
+
operation_id: "OP-1",
|
|
304
|
+
sale_date_time: "2026-06-01T10:00:00Z",
|
|
305
|
+
payer_nickname: "buyer-1",
|
|
306
|
+
transaction_amount: 100
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
items_info: [
|
|
310
|
+
{
|
|
311
|
+
item_id: "ITEM-1",
|
|
312
|
+
item_title: "Producto 1",
|
|
313
|
+
item_amount: 1,
|
|
314
|
+
item_price: 100,
|
|
315
|
+
item_kit_id: null,
|
|
316
|
+
store_id: "STORE-1",
|
|
317
|
+
order_id: overrides.order_id ?? "ORD-1"
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
...overrides
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
it("uses the official order details endpoint without site_id and chunks at 60 IDs", async () => {
|
|
326
|
+
axiosGetMock.mockResolvedValueOnce({ data: { results: [officialOrderRow({ order_id: "O1" })], total: 1, limit: 60 } }).mockResolvedValueOnce({ data: { results: [officialOrderRow({ order_id: "O61" })], total: 1, limit: 1 } });
|
|
327
|
+
const orderIds = Array.from({ length: 61 }, (_, index) => `O${index + 1}`);
|
|
328
|
+
const result = await getMercadoLibreBillingProvisionsByOrder("profile-1", {
|
|
329
|
+
orderIds
|
|
330
|
+
});
|
|
331
|
+
expect(axiosGetMock).toHaveBeenCalledTimes(2);
|
|
332
|
+
expect(axiosGetMock.mock.calls[0][0]).toBe("/billing/integration/group/ML/order/details");
|
|
333
|
+
expect(axiosGetMock.mock.calls[0][1]).toEqual({ params: { order_ids: orderIds.slice(0, 60).join(",") } });
|
|
334
|
+
expect(axiosGetMock.mock.calls[1][1]).toEqual({ params: { order_ids: ["O61"].join(",") } });
|
|
335
|
+
expect(result.chunks_total).toBe(2);
|
|
336
|
+
expect(result.chunks_succeeded).toBe(2);
|
|
337
|
+
expect(result.chunks_failed).toBe(0);
|
|
338
|
+
expect(result.order_ids_found).toEqual(["O1", "O61"]);
|
|
339
|
+
expect(result.order_ids_not_found).toEqual(orderIds.filter((id) => !["O1", "O61"].includes(id)));
|
|
340
|
+
});
|
|
341
|
+
it("deduplicates found order ids from the official per-order payload", async () => {
|
|
342
|
+
axiosGetMock.mockResolvedValue({
|
|
343
|
+
data: {
|
|
344
|
+
results: [
|
|
345
|
+
officialOrderRow({
|
|
346
|
+
order_id: "O1",
|
|
347
|
+
details: [
|
|
348
|
+
{
|
|
349
|
+
detail_id: "detail-1",
|
|
350
|
+
sales_info: [
|
|
351
|
+
{ order_id: "O1", operation_id: "OP-1", sale_date_time: "2026-06-01T10:00:00Z", payer_nickname: "buyer-1", transaction_amount: 100 }
|
|
352
|
+
],
|
|
353
|
+
items_info: [
|
|
354
|
+
{ item_id: "ITEM-1", item_title: "Producto 1", item_amount: 1, item_price: 100, order_id: "O1" }
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
})
|
|
359
|
+
],
|
|
360
|
+
total: 1,
|
|
361
|
+
limit: 60
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
const result = await getMercadoLibreBillingProvisionsByOrder("profile-1", {
|
|
365
|
+
orderIds: ["O1", "O2"]
|
|
366
|
+
});
|
|
367
|
+
expect(result.results).toHaveLength(1);
|
|
368
|
+
expect(result.order_ids_found).toEqual(["O1"]);
|
|
369
|
+
expect(result.order_ids_not_found).toEqual(["O2"]);
|
|
370
|
+
expect(result.coverage_complete).toBe(true);
|
|
371
|
+
});
|
|
372
|
+
it("returns the compact order, payment and detail blocks from the official payload", async () => {
|
|
373
|
+
axiosGetMock.mockResolvedValue({
|
|
374
|
+
data: {
|
|
375
|
+
results: [officialOrderRow({ order_id: "O1", sale_fee: null })],
|
|
376
|
+
total: 1,
|
|
377
|
+
limit: 60
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
const result = await meliGetBillingProvisionsByOrderHandler({
|
|
381
|
+
profileId: "profile-1",
|
|
382
|
+
orderIds: ["O1"]
|
|
383
|
+
});
|
|
384
|
+
expect(result).toHaveProperty("kind", "object");
|
|
385
|
+
const payload = result.payload;
|
|
386
|
+
expect(payload.profile_id).toBe("meli-profile-1");
|
|
387
|
+
expect(payload.endpoint).toBe("/billing/integration/group/ML/order/details");
|
|
388
|
+
expect(payload.orders_schema).toEqual(ordersSchema);
|
|
389
|
+
expect(payload.payment_info_schema).toEqual(paymentInfoSchema);
|
|
390
|
+
expect(payload.details_schema).toEqual(byOrderDetailsSchema);
|
|
391
|
+
expect(payload.details_sales_schema).toEqual(byOrderDetailsSalesSchema);
|
|
392
|
+
expect(payload.details_items_schema).toEqual(byOrderDetailsItemsSchema);
|
|
393
|
+
const orders = payload.orders;
|
|
394
|
+
const paymentInfo = payload.payment_info;
|
|
395
|
+
const details = payload.details;
|
|
396
|
+
const detailsSales = payload.details_sales;
|
|
397
|
+
const detailsItems = payload.details_items;
|
|
398
|
+
expect(orders).toHaveLength(1);
|
|
399
|
+
expect(orders[0][0]).toBe("O1");
|
|
400
|
+
expect(orders[0][1]).toBeNull();
|
|
401
|
+
expect(paymentInfo).toHaveLength(1);
|
|
402
|
+
expect(paymentInfo[0][0]).toBe("O1");
|
|
403
|
+
expect(details).toHaveLength(1);
|
|
404
|
+
expect(details[0][0]).toBe("O1");
|
|
405
|
+
expect(detailsSales).toHaveLength(1);
|
|
406
|
+
expect(detailsItems).toHaveLength(1);
|
|
407
|
+
const metadata = payload.metadata;
|
|
408
|
+
expect(metadata.order_ids_requested).toEqual(["O1"]);
|
|
409
|
+
expect(metadata.order_ids_found).toEqual(["O1"]);
|
|
410
|
+
expect(metadata.order_ids_not_found).toEqual([]);
|
|
411
|
+
expect(metadata.coverage_complete).toBe(true);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
238
414
|
describe("meliGetBillingProvisionsSummaryHandler", () => {
|
|
239
415
|
beforeEach(() => {
|
|
240
416
|
vi.clearAllMocks();
|