@yoryoboy/bi-mcp 1.16.0 → 1.19.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/README.md +12 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.js +179 -6
- package/dist/index.js.map +2 -2
- package/dist/mcp-use.json +3 -6
- package/dist/src/config/__tests__/google-store.test.js +30 -0
- package/dist/src/config/__tests__/google-store.test.js.map +7 -0
- package/dist/src/config/__tests__/mcp-tool-deadline.test.js +64 -0
- package/dist/src/config/__tests__/mcp-tool-deadline.test.js.map +7 -0
- package/dist/src/config/google-store.js +18 -0
- package/dist/src/config/google-store.js.map +2 -2
- package/dist/src/config/mcp-tool-deadline-context.js +34 -0
- package/dist/src/config/mcp-tool-deadline-context.js.map +7 -0
- package/dist/src/config/mcp-tool-deadline.js +67 -0
- package/dist/src/config/mcp-tool-deadline.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-api.test.js +38 -3
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-api.test.js.map +2 -2
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-buyer-reconciliation.test.js +226 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-buyer-reconciliation.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-claim-reconciliation.test.js +127 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-claim-reconciliation.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-kits.test.js +103 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-kits.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-order-billing-info.test.js +582 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-order-billing-info.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-orders.test.js +10 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-orders.test.js.map +2 -2
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-packs.test.js +36 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-packs.test.js.map +7 -0
- 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/__tests__/mercadolibre-product-ads-ad-group-ads.test.js +105 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads-ad-group-ads.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads-ad-groups.test.js +143 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads-ad-groups.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads-campaigns.test.js +100 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads-campaigns.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads.test.js +350 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-product-ads.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-return-reconciliation.test.js +228 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-return-reconciliation.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-shipping.test.js +58 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-shipping.test.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-api.js +15 -3
- package/dist/src/services/mercadolibre/mercadolibre-api.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-billing.js +110 -3
- package/dist/src/services/mercadolibre/mercadolibre-billing.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-buyer-reconciliation.js +368 -0
- package/dist/src/services/mercadolibre/mercadolibre-buyer-reconciliation.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-claim-reconciliation.js +399 -0
- package/dist/src/services/mercadolibre/mercadolibre-claim-reconciliation.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-kits.js +55 -0
- package/dist/src/services/mercadolibre/mercadolibre-kits.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-order-billing-info.js +392 -0
- package/dist/src/services/mercadolibre/mercadolibre-order-billing-info.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-orders.js +8 -8
- package/dist/src/services/mercadolibre/mercadolibre-orders.js.map +2 -2
- package/dist/src/services/mercadolibre/mercadolibre-packs.js +21 -0
- package/dist/src/services/mercadolibre/mercadolibre-packs.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-payments.js +60 -0
- package/dist/src/services/mercadolibre/mercadolibre-payments.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-product-ads.js +429 -0
- package/dist/src/services/mercadolibre/mercadolibre-product-ads.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-return-reconciliation.js +436 -0
- package/dist/src/services/mercadolibre/mercadolibre-return-reconciliation.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-shipping.js +35 -0
- package/dist/src/services/mercadolibre/mercadolibre-shipping.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-api.test.js +67 -0
- package/dist/src/services/vtex/__tests__/vtex-api.test.js.map +7 -0
- package/dist/src/services/vtex/vtex-api.js +6 -0
- package/dist/src/services/vtex/vtex-api.js.map +2 -2
- package/dist/src/tools/config/__tests__/list-profiles.test.js +154 -0
- package/dist/src/tools/config/__tests__/list-profiles.test.js.map +7 -0
- package/dist/src/tools/config/list-profiles.js +39 -3
- package/dist/src/tools/config/list-profiles.js.map +2 -2
- package/dist/src/tools/mercadolibre/__tests__/get-order-billing-info.test.js +339 -0
- package/dist/src/tools/mercadolibre/__tests__/get-order-billing-info.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-ad-group-ads.test.js +225 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-ad-group-ads.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-ad-groups.test.js +148 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-ad-groups.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-campaigns.test.js +60 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-campaigns.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-helpers.test.js +128 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-helpers.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-tools.test.js +435 -0
- package/dist/src/tools/mercadolibre/__tests__/product-ads-tools.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/reconcile-buyer-data.test.js +31 -0
- package/dist/src/tools/mercadolibre/__tests__/reconcile-buyer-data.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/reconcile-claim-data.test.js +36 -0
- package/dist/src/tools/mercadolibre/__tests__/reconcile-claim-data.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/__tests__/validate-connection.test.js +205 -0
- package/dist/src/tools/mercadolibre/__tests__/validate-connection.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-billing-provisions-by-order.js +313 -0
- package/dist/src/tools/mercadolibre/get-billing-provisions-by-order.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-bundle-context-by-item.js +176 -0
- package/dist/src/tools/mercadolibre/get-bundle-context-by-item.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-order-billing-info.js +189 -0
- package/dist/src/tools/mercadolibre/get-order-billing-info.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-pack-context-by-order.js +150 -0
- package/dist/src/tools/mercadolibre/get-pack-context-by-order.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/get-product-ads-ad-group-ads.js +144 -0
- package/dist/src/tools/mercadolibre/get-product-ads-ad-group-ads.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-product-ads-advertisers.js +59 -0
- package/dist/src/tools/mercadolibre/get-product-ads-advertisers.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-shipping-quote-by-declared-dimensions.js +104 -0
- package/dist/src/tools/mercadolibre/get-shipping-quote-by-declared-dimensions.js.map +7 -0
- package/dist/src/tools/mercadolibre/index.js +32 -0
- package/dist/src/tools/mercadolibre/index.js.map +2 -2
- package/dist/src/tools/mercadolibre/product-ads-helpers.js +130 -0
- package/dist/src/tools/mercadolibre/product-ads-helpers.js.map +7 -0
- package/dist/src/tools/mercadolibre/reconcile-buyer-data.js +27 -0
- package/dist/src/tools/mercadolibre/reconcile-buyer-data.js.map +7 -0
- package/dist/src/tools/mercadolibre/reconcile-claim-data.js +46 -0
- package/dist/src/tools/mercadolibre/reconcile-claim-data.js.map +7 -0
- package/dist/src/tools/mercadolibre/reconcile-return-data.js +25 -0
- package/dist/src/tools/mercadolibre/reconcile-return-data.js.map +7 -0
- package/dist/src/tools/mercadolibre/search-product-ads-ad-groups.js +162 -0
- package/dist/src/tools/mercadolibre/search-product-ads-ad-groups.js.map +7 -0
- package/dist/src/tools/mercadolibre/search-product-ads-ads.js +216 -0
- package/dist/src/tools/mercadolibre/search-product-ads-ads.js.map +7 -0
- package/dist/src/tools/mercadolibre/search-product-ads-campaigns.js +116 -0
- package/dist/src/tools/mercadolibre/search-product-ads-campaigns.js.map +7 -0
- package/dist/src/tools/mercadolibre/validate-connection.js +40 -12
- package/dist/src/tools/mercadolibre/validate-connection.js.map +2 -2
- package/dist/tests/meli/mercadolibre-billing-provisions.test.js +378 -0
- package/dist/tests/meli/mercadolibre-billing-provisions.test.js.map +2 -2
- package/dist/tests/meli/mercadolibre-order-billing-info-surface.test.js +123 -0
- package/dist/tests/meli/mercadolibre-order-billing-info-surface.test.js.map +7 -0
- 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/dist/tests/meli/mercadolibre-product-ads-ad-groups-surface.test.js +90 -0
- package/dist/tests/meli/mercadolibre-product-ads-ad-groups-surface.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-product-ads-campaigns-surface.test.js +72 -0
- package/dist/tests/meli/mercadolibre-product-ads-campaigns-surface.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-pack-kit-shipping.test.js +400 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-pack-kit-shipping.test.js.map +7 -0
- package/dist/tests/meli/mercadolibre-tool-handlers-small.test.js +31 -12
- package/dist/tests/meli/mercadolibre-tool-handlers-small.test.js.map +2 -2
- package/dist/tests/vtex/vtex-commercial-conditions-docs.test.js +1 -1
- package/dist/tests/vtex/vtex-commercial-conditions-docs.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/google-ads/report-utils.js +0 -78
- package/dist/src/google-ads/report-utils.js.map +0 -7
- package/dist/src/search-console/search-console-utils.js +0 -275
- package/dist/src/search-console/search-console-utils.js.map +0 -7
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js +0 -165
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js.map +0 -7
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js +0 -233
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js.map +0 -7
- package/dist/src/tools/vtex/catalog-admin-batch.js +0 -298
- package/dist/src/tools/vtex/catalog-admin-batch.js.map +0 -7
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { meliValidateConnectionHandler } from "../validate-connection.js";
|
|
3
|
+
import { resolveMercadoLibreProfileOrSelection } from "../profile-resolution.js";
|
|
4
|
+
import {
|
|
5
|
+
getMercadoLibreConnectionRow,
|
|
6
|
+
markMercadoLibreConnectionValidation,
|
|
7
|
+
updateMercadoLibreConnectionTokens
|
|
8
|
+
} from "../../../config/mercadolibre-profile-store.js";
|
|
9
|
+
import { decryptSecret } from "../../../config/vtex-crypto.js";
|
|
10
|
+
import {
|
|
11
|
+
formatMercadoLibreError,
|
|
12
|
+
getMercadoLibreUsersMeWithAccessToken
|
|
13
|
+
} from "../../../services/mercadolibre/mercadolibre-api.js";
|
|
14
|
+
vi.mock("mcp-use/server", () => ({
|
|
15
|
+
object: vi.fn((payload) => ({ kind: "object", payload })),
|
|
16
|
+
error: vi.fn((message) => ({ kind: "error", message }))
|
|
17
|
+
}));
|
|
18
|
+
vi.mock("../profile-resolution.js", () => ({
|
|
19
|
+
resolveMercadoLibreProfileOrSelection: vi.fn()
|
|
20
|
+
}));
|
|
21
|
+
vi.mock("../write-helpers.js", async () => {
|
|
22
|
+
const { z } = await import("zod");
|
|
23
|
+
return { mercadolibreProfileIdSchemaField: z.string().optional() };
|
|
24
|
+
});
|
|
25
|
+
vi.mock("../../../config/mercadolibre-profile-store.js", () => ({
|
|
26
|
+
getMercadoLibreConnectionRow: vi.fn(),
|
|
27
|
+
markMercadoLibreConnectionValidation: vi.fn(),
|
|
28
|
+
updateMercadoLibreConnectionTokens: vi.fn()
|
|
29
|
+
}));
|
|
30
|
+
vi.mock("../../../config/vtex-crypto.js", () => ({
|
|
31
|
+
decryptSecret: vi.fn()
|
|
32
|
+
}));
|
|
33
|
+
vi.mock("../../../services/mercadolibre/mercadolibre-api.js", () => ({
|
|
34
|
+
getMercadoLibreUsersMeWithAccessToken: vi.fn(),
|
|
35
|
+
formatMercadoLibreError: vi.fn((_err, fallback) => `safe:${fallback}`)
|
|
36
|
+
}));
|
|
37
|
+
const usableConnection = {
|
|
38
|
+
sellerId: "seller-99",
|
|
39
|
+
encryptedAccessToken: "encrypted-token",
|
|
40
|
+
expiresAt: /* @__PURE__ */ new Date("2099-01-01T00:00:00.000Z"),
|
|
41
|
+
scopes: ["read"],
|
|
42
|
+
status: "error"
|
|
43
|
+
};
|
|
44
|
+
function expectNoPersistence() {
|
|
45
|
+
expect(markMercadoLibreConnectionValidation).not.toHaveBeenCalled();
|
|
46
|
+
expect(updateMercadoLibreConnectionTokens).not.toHaveBeenCalled();
|
|
47
|
+
}
|
|
48
|
+
describe("meliValidateConnectionHandler", () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
vi.clearAllMocks();
|
|
51
|
+
vi.useFakeTimers();
|
|
52
|
+
vi.setSystemTime(/* @__PURE__ */ new Date("2026-07-10T12:00:00.000Z"));
|
|
53
|
+
vi.mocked(resolveMercadoLibreProfileOrSelection).mockResolvedValue({
|
|
54
|
+
ok: true,
|
|
55
|
+
value: { profileId: "meli-profile-1" }
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
vi.useRealTimers();
|
|
60
|
+
});
|
|
61
|
+
it("reports a missing connection as credential maintenance without probing or persisting", async () => {
|
|
62
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(null);
|
|
63
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
64
|
+
expect(result).toEqual({
|
|
65
|
+
kind: "object",
|
|
66
|
+
payload: {
|
|
67
|
+
profile_id: "meli-profile-1",
|
|
68
|
+
observation_only: true,
|
|
69
|
+
validation_status: "credential_maintenance_required",
|
|
70
|
+
credential_status: "connection_not_found",
|
|
71
|
+
message: "No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state."
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
expect(decryptSecret).not.toHaveBeenCalled();
|
|
75
|
+
expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();
|
|
76
|
+
expectNoPersistence();
|
|
77
|
+
});
|
|
78
|
+
it("reports a disabled connection as credential maintenance without probing or persisting", async () => {
|
|
79
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({
|
|
80
|
+
...usableConnection,
|
|
81
|
+
status: "disabled"
|
|
82
|
+
});
|
|
83
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
84
|
+
expect(result).toEqual({
|
|
85
|
+
kind: "object",
|
|
86
|
+
payload: {
|
|
87
|
+
profile_id: "meli-profile-1",
|
|
88
|
+
observation_only: true,
|
|
89
|
+
validation_status: "credential_maintenance_required",
|
|
90
|
+
credential_status: "connection_disabled",
|
|
91
|
+
expires_at: "2099-01-01T00:00:00.000Z",
|
|
92
|
+
message: "No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state."
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
expect(decryptSecret).not.toHaveBeenCalled();
|
|
96
|
+
expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();
|
|
97
|
+
expectNoPersistence();
|
|
98
|
+
});
|
|
99
|
+
it("reports a missing token as credential maintenance without probing or persisting", async () => {
|
|
100
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({
|
|
101
|
+
...usableConnection,
|
|
102
|
+
encryptedAccessToken: ""
|
|
103
|
+
});
|
|
104
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
105
|
+
expect(result).toMatchObject({
|
|
106
|
+
kind: "object",
|
|
107
|
+
payload: {
|
|
108
|
+
profile_id: "meli-profile-1",
|
|
109
|
+
observation_only: true,
|
|
110
|
+
validation_status: "credential_maintenance_required",
|
|
111
|
+
credential_status: "token_missing",
|
|
112
|
+
expires_at: "2099-01-01T00:00:00.000Z"
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
expect(decryptSecret).not.toHaveBeenCalled();
|
|
116
|
+
expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();
|
|
117
|
+
expectNoPersistence();
|
|
118
|
+
});
|
|
119
|
+
it("reports an unknown expiry as credential maintenance without probing or persisting", async () => {
|
|
120
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({
|
|
121
|
+
...usableConnection,
|
|
122
|
+
expiresAt: null
|
|
123
|
+
});
|
|
124
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
125
|
+
expect(result).toMatchObject({
|
|
126
|
+
kind: "object",
|
|
127
|
+
payload: {
|
|
128
|
+
profile_id: "meli-profile-1",
|
|
129
|
+
observation_only: true,
|
|
130
|
+
validation_status: "credential_maintenance_required",
|
|
131
|
+
credential_status: "expiry_unknown"
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
expect(result).not.toMatchObject({
|
|
135
|
+
payload: { expires_at: expect.anything() }
|
|
136
|
+
});
|
|
137
|
+
expect(decryptSecret).not.toHaveBeenCalled();
|
|
138
|
+
expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();
|
|
139
|
+
expectNoPersistence();
|
|
140
|
+
});
|
|
141
|
+
it("probes /users/me with the persisted unexpired token without changing connection state", async () => {
|
|
142
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(usableConnection);
|
|
143
|
+
vi.mocked(decryptSecret).mockReturnValue("stored-access-token");
|
|
144
|
+
vi.mocked(getMercadoLibreUsersMeWithAccessToken).mockResolvedValue({
|
|
145
|
+
id: 12345,
|
|
146
|
+
nickname: "meli-store"
|
|
147
|
+
});
|
|
148
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
149
|
+
expect(getMercadoLibreUsersMeWithAccessToken).toHaveBeenCalledWith("stored-access-token");
|
|
150
|
+
expect(result).toEqual({
|
|
151
|
+
kind: "object",
|
|
152
|
+
payload: {
|
|
153
|
+
profile_id: "meli-profile-1",
|
|
154
|
+
observation_only: true,
|
|
155
|
+
validation_status: "valid",
|
|
156
|
+
seller_id: "seller-99",
|
|
157
|
+
account_id: 12345,
|
|
158
|
+
nickname: "meli-store",
|
|
159
|
+
expires_at: "2099-01-01T00:00:00.000Z",
|
|
160
|
+
scopes: ["read"]
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
expectNoPersistence();
|
|
164
|
+
});
|
|
165
|
+
it("reports expired credentials without decrypting, refreshing, or persisting tokens", async () => {
|
|
166
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({
|
|
167
|
+
...usableConnection,
|
|
168
|
+
expiresAt: /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z")
|
|
169
|
+
});
|
|
170
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
171
|
+
expect(result).toEqual({
|
|
172
|
+
kind: "object",
|
|
173
|
+
payload: {
|
|
174
|
+
profile_id: "meli-profile-1",
|
|
175
|
+
observation_only: true,
|
|
176
|
+
validation_status: "credential_maintenance_required",
|
|
177
|
+
credential_status: "token_expired",
|
|
178
|
+
expires_at: "2000-01-01T00:00:00.000Z",
|
|
179
|
+
message: "No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state."
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
expect(decryptSecret).not.toHaveBeenCalled();
|
|
183
|
+
expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();
|
|
184
|
+
expectNoPersistence();
|
|
185
|
+
});
|
|
186
|
+
it("returns a safe upstream probe error without mutating connection state", async () => {
|
|
187
|
+
vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(usableConnection);
|
|
188
|
+
vi.mocked(decryptSecret).mockReturnValue("stored-access-token");
|
|
189
|
+
vi.mocked(getMercadoLibreUsersMeWithAccessToken).mockRejectedValue(
|
|
190
|
+
new Error("upstream unavailable: Bearer stored-access-token access_token=stored-access-token")
|
|
191
|
+
);
|
|
192
|
+
const result = await meliValidateConnectionHandler({ profileId: "meli-profile-1" });
|
|
193
|
+
expect(formatMercadoLibreError).toHaveBeenCalledWith(
|
|
194
|
+
expect.any(Error),
|
|
195
|
+
"Failed to validate MercadoLibre connection"
|
|
196
|
+
);
|
|
197
|
+
expect(result).toEqual({
|
|
198
|
+
kind: "error",
|
|
199
|
+
message: "safe:Failed to validate MercadoLibre connection"
|
|
200
|
+
});
|
|
201
|
+
expect(JSON.stringify(result)).not.toContain("stored-access-token");
|
|
202
|
+
expectNoPersistence();
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=validate-connection.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/mercadolibre/__tests__/validate-connection.test.ts"],
|
|
4
|
+
"sourcesContent": ["import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { meliValidateConnectionHandler } from \"../validate-connection.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"../profile-resolution.js\";\nimport {\n getMercadoLibreConnectionRow,\n markMercadoLibreConnectionValidation,\n updateMercadoLibreConnectionTokens,\n} from \"../../../config/mercadolibre-profile-store.js\";\nimport { decryptSecret } from \"../../../config/vtex-crypto.js\";\nimport {\n formatMercadoLibreError,\n getMercadoLibreUsersMeWithAccessToken,\n} from \"../../../services/mercadolibre/mercadolibre-api.js\";\n\nvi.mock(\"mcp-use/server\", () => ({\n object: vi.fn((payload: unknown) => ({ kind: \"object\", payload })),\n error: vi.fn((message: string) => ({ kind: \"error\", message })),\n}));\n\nvi.mock(\"../profile-resolution.js\", () => ({\n resolveMercadoLibreProfileOrSelection: vi.fn(),\n}));\n\nvi.mock(\"../write-helpers.js\", async () => {\n const { z } = await import(\"zod\");\n return { mercadolibreProfileIdSchemaField: z.string().optional() };\n});\n\nvi.mock(\"../../../config/mercadolibre-profile-store.js\", () => ({\n getMercadoLibreConnectionRow: vi.fn(),\n markMercadoLibreConnectionValidation: vi.fn(),\n updateMercadoLibreConnectionTokens: vi.fn(),\n}));\n\nvi.mock(\"../../../config/vtex-crypto.js\", () => ({\n decryptSecret: vi.fn(),\n}));\n\nvi.mock(\"../../../services/mercadolibre/mercadolibre-api.js\", () => ({\n getMercadoLibreUsersMeWithAccessToken: vi.fn(),\n formatMercadoLibreError: vi.fn((_err: unknown, fallback: string) => `safe:${fallback}`),\n}));\n\nconst usableConnection = {\n sellerId: \"seller-99\",\n encryptedAccessToken: \"encrypted-token\",\n expiresAt: new Date(\"2099-01-01T00:00:00.000Z\"),\n scopes: [\"read\"],\n status: \"error\",\n};\n\nfunction expectNoPersistence() {\n expect(markMercadoLibreConnectionValidation).not.toHaveBeenCalled();\n expect(updateMercadoLibreConnectionTokens).not.toHaveBeenCalled();\n}\n\ndescribe(\"meliValidateConnectionHandler\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n vi.useFakeTimers();\n vi.setSystemTime(new Date(\"2026-07-10T12:00:00.000Z\"));\n vi.mocked(resolveMercadoLibreProfileOrSelection).mockResolvedValue({\n ok: true,\n value: { profileId: \"meli-profile-1\" },\n });\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it(\"reports a missing connection as credential maintenance without probing or persisting\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(null);\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(result).toEqual({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"credential_maintenance_required\",\n credential_status: \"connection_not_found\",\n message:\n \"No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state.\",\n },\n });\n expect(decryptSecret).not.toHaveBeenCalled();\n expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();\n expectNoPersistence();\n });\n\n it(\"reports a disabled connection as credential maintenance without probing or persisting\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({\n ...usableConnection,\n status: \"disabled\",\n } as never);\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(result).toEqual({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"credential_maintenance_required\",\n credential_status: \"connection_disabled\",\n expires_at: \"2099-01-01T00:00:00.000Z\",\n message:\n \"No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state.\",\n },\n });\n expect(decryptSecret).not.toHaveBeenCalled();\n expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();\n expectNoPersistence();\n });\n\n it(\"reports a missing token as credential maintenance without probing or persisting\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({\n ...usableConnection,\n encryptedAccessToken: \"\",\n } as never);\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(result).toMatchObject({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"credential_maintenance_required\",\n credential_status: \"token_missing\",\n expires_at: \"2099-01-01T00:00:00.000Z\",\n },\n });\n expect(decryptSecret).not.toHaveBeenCalled();\n expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();\n expectNoPersistence();\n });\n\n it(\"reports an unknown expiry as credential maintenance without probing or persisting\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({\n ...usableConnection,\n expiresAt: null,\n } as never);\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(result).toMatchObject({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"credential_maintenance_required\",\n credential_status: \"expiry_unknown\",\n },\n });\n expect(result).not.toMatchObject({\n payload: { expires_at: expect.anything() },\n });\n expect(decryptSecret).not.toHaveBeenCalled();\n expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();\n expectNoPersistence();\n });\n\n it(\"probes /users/me with the persisted unexpired token without changing connection state\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(usableConnection as never);\n vi.mocked(decryptSecret).mockReturnValue(\"stored-access-token\");\n vi.mocked(getMercadoLibreUsersMeWithAccessToken).mockResolvedValue({\n id: 12345,\n nickname: \"meli-store\",\n });\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(getMercadoLibreUsersMeWithAccessToken).toHaveBeenCalledWith(\"stored-access-token\");\n expect(result).toEqual({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"valid\",\n seller_id: \"seller-99\",\n account_id: 12345,\n nickname: \"meli-store\",\n expires_at: \"2099-01-01T00:00:00.000Z\",\n scopes: [\"read\"],\n },\n });\n expectNoPersistence();\n });\n\n it(\"reports expired credentials without decrypting, refreshing, or persisting tokens\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue({\n ...usableConnection,\n expiresAt: new Date(\"2000-01-01T00:00:00.000Z\"),\n } as never);\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(result).toEqual({\n kind: \"object\",\n payload: {\n profile_id: \"meli-profile-1\",\n observation_only: true,\n validation_status: \"credential_maintenance_required\",\n credential_status: \"token_expired\",\n expires_at: \"2000-01-01T00:00:00.000Z\",\n message:\n \"No usable unexpired stored access token is available. Credential maintenance or refresh is required; this observation-only validation did not refresh tokens or update connection state.\",\n },\n });\n expect(decryptSecret).not.toHaveBeenCalled();\n expect(getMercadoLibreUsersMeWithAccessToken).not.toHaveBeenCalled();\n expectNoPersistence();\n });\n\n it(\"returns a safe upstream probe error without mutating connection state\", async () => {\n vi.mocked(getMercadoLibreConnectionRow).mockResolvedValue(usableConnection as never);\n vi.mocked(decryptSecret).mockReturnValue(\"stored-access-token\");\n vi.mocked(getMercadoLibreUsersMeWithAccessToken).mockRejectedValue(\n new Error(\"upstream unavailable: Bearer stored-access-token access_token=stored-access-token\")\n );\n\n const result = await meliValidateConnectionHandler({ profileId: \"meli-profile-1\" });\n\n expect(formatMercadoLibreError).toHaveBeenCalledWith(\n expect.any(Error),\n \"Failed to validate MercadoLibre connection\"\n );\n expect(result).toEqual({\n kind: \"error\",\n message: \"safe:Failed to validate MercadoLibre connection\",\n });\n expect(JSON.stringify(result)).not.toContain(\"stored-access-token\");\n expectNoPersistence();\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
formatMercadoLibreError
|
|
5
|
+
} from "../../services/mercadolibre/mercadolibre-api.js";
|
|
6
|
+
import {
|
|
7
|
+
getMercadoLibreBillingProvisionsByOrder
|
|
8
|
+
} from "../../services/mercadolibre/mercadolibre-billing.js";
|
|
9
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
10
|
+
import {
|
|
11
|
+
asRecord,
|
|
12
|
+
normalizeScalarString
|
|
13
|
+
} from "./helpers.js";
|
|
14
|
+
import { resolveMercadoLibreProfileOrSelection } from "./profile-resolution.js";
|
|
15
|
+
const meliGetBillingProvisionsByOrderSchema = z.object({
|
|
16
|
+
profileId: z.string().trim().min(1).describe("Explicit MercadoLibre profile id to use."),
|
|
17
|
+
orderIds: z.array(z.string().trim().min(1).describe("MercadoLibre order id.")).min(1).describe("One or more MercadoLibre order IDs to fetch billing provisions for.")
|
|
18
|
+
});
|
|
19
|
+
const ordersSchema = [
|
|
20
|
+
"order_id",
|
|
21
|
+
"sale_fee",
|
|
22
|
+
"payment_info_count",
|
|
23
|
+
"detail_count",
|
|
24
|
+
"document_id",
|
|
25
|
+
"currency_id",
|
|
26
|
+
"marketplace"
|
|
27
|
+
];
|
|
28
|
+
const paymentInfoSchema = [
|
|
29
|
+
"order_id",
|
|
30
|
+
"payment_id",
|
|
31
|
+
"payment_type",
|
|
32
|
+
"payment_method_id",
|
|
33
|
+
"installments",
|
|
34
|
+
"transaction_amount",
|
|
35
|
+
"total_paid_amount",
|
|
36
|
+
"shipping_cost",
|
|
37
|
+
"coupon_amount",
|
|
38
|
+
"status",
|
|
39
|
+
"status_detail"
|
|
40
|
+
];
|
|
41
|
+
const detailsSchema = [
|
|
42
|
+
"order_id",
|
|
43
|
+
"detail_id",
|
|
44
|
+
"detail_type",
|
|
45
|
+
"detail_sub_type",
|
|
46
|
+
"transaction_detail",
|
|
47
|
+
"detail_amount",
|
|
48
|
+
"currency_id",
|
|
49
|
+
"concept_type",
|
|
50
|
+
"operation_id",
|
|
51
|
+
"shipping_id",
|
|
52
|
+
"pack_id",
|
|
53
|
+
"inventory_id"
|
|
54
|
+
];
|
|
55
|
+
const detailsSalesSchema = [
|
|
56
|
+
"detail_id",
|
|
57
|
+
"order_id",
|
|
58
|
+
"operation_id",
|
|
59
|
+
"sale_date_time",
|
|
60
|
+
"payer_nickname",
|
|
61
|
+
"transaction_amount"
|
|
62
|
+
];
|
|
63
|
+
const detailsItemsSchema = [
|
|
64
|
+
"detail_id",
|
|
65
|
+
"item_id",
|
|
66
|
+
"item_title",
|
|
67
|
+
"item_amount",
|
|
68
|
+
"item_price",
|
|
69
|
+
"item_kit_id",
|
|
70
|
+
"store_id",
|
|
71
|
+
"order_id",
|
|
72
|
+
"fees_added_in_publication"
|
|
73
|
+
];
|
|
74
|
+
function asRecordArray(value) {
|
|
75
|
+
if (Array.isArray(value)) {
|
|
76
|
+
return value.filter(
|
|
77
|
+
(entry) => entry != null && typeof entry === "object" && !Array.isArray(entry)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const record = asRecord(value);
|
|
81
|
+
return Object.keys(record).length > 0 ? [record] : [];
|
|
82
|
+
}
|
|
83
|
+
function toOptionalNumber(value) {
|
|
84
|
+
if (typeof value === "number") {
|
|
85
|
+
return Number.isFinite(value) ? value : null;
|
|
86
|
+
}
|
|
87
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const numericValue = Number(value);
|
|
91
|
+
return Number.isFinite(numericValue) ? numericValue : null;
|
|
92
|
+
}
|
|
93
|
+
function normalizeFeesAddedInPublication(value) {
|
|
94
|
+
return value === "Si" || value === "No" ? value : null;
|
|
95
|
+
}
|
|
96
|
+
function resolveDetailOrderId(detail, fallbackOrderId) {
|
|
97
|
+
const salesInfo = asRecordArray(detail.sales_info ?? detail.details_sales);
|
|
98
|
+
return normalizeScalarString(salesInfo[0]?.order_id) || normalizeScalarString(detail.order_id) || fallbackOrderId;
|
|
99
|
+
}
|
|
100
|
+
function projectOrderRow(row) {
|
|
101
|
+
const paymentInfo = asRecordArray(row.payment_info);
|
|
102
|
+
const details = asRecordArray(row.details);
|
|
103
|
+
const firstDetail = details[0] ?? {};
|
|
104
|
+
const orderId = normalizeScalarString(row.order_id) || normalizeScalarString(paymentInfo[0]?.order_id) || normalizeScalarString(firstDetail.order_id) || resolveDetailOrderId(firstDetail, null) || null;
|
|
105
|
+
const documentInfo = asRecord(row.document_info);
|
|
106
|
+
const currencyInfo = asRecord(row.currency_info);
|
|
107
|
+
const marketplaceInfo = asRecord(row.marketplace_info);
|
|
108
|
+
return [
|
|
109
|
+
orderId,
|
|
110
|
+
// 0: order_id
|
|
111
|
+
toOptionalNumber(row.sale_fee),
|
|
112
|
+
// 1: sale_fee
|
|
113
|
+
paymentInfo.length,
|
|
114
|
+
// 2: payment_info_count
|
|
115
|
+
details.length,
|
|
116
|
+
// 3: detail_count
|
|
117
|
+
normalizeScalarString(documentInfo.document_id ?? row.document_id) || null,
|
|
118
|
+
// 4: document_id
|
|
119
|
+
normalizeScalarString(currencyInfo.currency_id ?? row.currency_id) || null,
|
|
120
|
+
// 5: currency_id
|
|
121
|
+
normalizeScalarString(marketplaceInfo.marketplace ?? row.marketplace) || null
|
|
122
|
+
// 6: marketplace
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
function projectPaymentRow(orderId, payment) {
|
|
126
|
+
return [
|
|
127
|
+
orderId,
|
|
128
|
+
// 0: order_id
|
|
129
|
+
normalizeScalarString(payment.payment_id ?? payment.id) || null,
|
|
130
|
+
// 1: payment_id
|
|
131
|
+
normalizeScalarString(payment.payment_type) || null,
|
|
132
|
+
// 2: payment_type
|
|
133
|
+
normalizeScalarString(payment.payment_method_id) || null,
|
|
134
|
+
// 3: payment_method_id
|
|
135
|
+
toOptionalNumber(payment.installments),
|
|
136
|
+
// 4: installments
|
|
137
|
+
toOptionalNumber(payment.transaction_amount),
|
|
138
|
+
// 5: transaction_amount
|
|
139
|
+
toOptionalNumber(payment.total_paid_amount),
|
|
140
|
+
// 6: total_paid_amount
|
|
141
|
+
toOptionalNumber(payment.shipping_cost),
|
|
142
|
+
// 7: shipping_cost
|
|
143
|
+
toOptionalNumber(payment.coupon_amount),
|
|
144
|
+
// 8: coupon_amount
|
|
145
|
+
normalizeScalarString(payment.status) || null,
|
|
146
|
+
// 9: status
|
|
147
|
+
normalizeScalarString(payment.status_detail) || null
|
|
148
|
+
// 10: status_detail
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
function projectDetailRow(orderId, detail, fallbackCurrencyId) {
|
|
152
|
+
const chargeInfo = asRecord(detail.charge_info);
|
|
153
|
+
const currencyInfo = asRecord(detail.currency_info);
|
|
154
|
+
const detailOrderId = resolveDetailOrderId(detail, orderId);
|
|
155
|
+
const detailAmount = chargeInfo.detail_amount ?? detail.detail_amount;
|
|
156
|
+
return [
|
|
157
|
+
detailOrderId,
|
|
158
|
+
// 0: order_id
|
|
159
|
+
normalizeScalarString(chargeInfo.detail_id ?? detail.detail_id) || null,
|
|
160
|
+
// 1: detail_id
|
|
161
|
+
normalizeScalarString(chargeInfo.detail_type ?? detail.detail_type) || null,
|
|
162
|
+
// 2: detail_type
|
|
163
|
+
normalizeScalarString(chargeInfo.detail_sub_type ?? detail.detail_sub_type) || null,
|
|
164
|
+
// 3: detail_sub_type
|
|
165
|
+
normalizeScalarString(chargeInfo.transaction_detail ?? detail.transaction_detail) || null,
|
|
166
|
+
// 4: transaction_detail
|
|
167
|
+
toOptionalNumber(detailAmount),
|
|
168
|
+
// 5: detail_amount
|
|
169
|
+
normalizeScalarString(currencyInfo.currency_id ?? detail.currency_id) || fallbackCurrencyId,
|
|
170
|
+
// 6: currency_id
|
|
171
|
+
normalizeScalarString(chargeInfo.concept_type ?? detail.concept_type) || null,
|
|
172
|
+
// 7: concept_type
|
|
173
|
+
normalizeScalarString(chargeInfo.operation_id ?? detail.operation_id) || null,
|
|
174
|
+
// 8: operation_id
|
|
175
|
+
normalizeScalarString(chargeInfo.shipping_id ?? detail.shipping_id) || null,
|
|
176
|
+
// 9: shipping_id
|
|
177
|
+
normalizeScalarString(chargeInfo.pack_id ?? detail.pack_id) || null,
|
|
178
|
+
// 10: pack_id
|
|
179
|
+
normalizeScalarString(chargeInfo.inventory_id ?? detail.inventory_id) || null
|
|
180
|
+
// 11: inventory_id
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
function projectSalesRow(detailId, sale) {
|
|
184
|
+
return [
|
|
185
|
+
detailId,
|
|
186
|
+
// 0: detail_id
|
|
187
|
+
normalizeScalarString(sale.order_id) || null,
|
|
188
|
+
// 1: order_id
|
|
189
|
+
normalizeScalarString(sale.operation_id) || null,
|
|
190
|
+
// 2: operation_id
|
|
191
|
+
normalizeScalarString(sale.sale_date_time) || null,
|
|
192
|
+
// 3: sale_date_time
|
|
193
|
+
null,
|
|
194
|
+
// 4: payer_nickname (redacted)
|
|
195
|
+
toOptionalNumber(sale.transaction_amount)
|
|
196
|
+
// 5: transaction_amount
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
function projectItemsRow(detailId, detailOrderId, item) {
|
|
200
|
+
return [
|
|
201
|
+
detailId,
|
|
202
|
+
// 0: detail_id
|
|
203
|
+
normalizeScalarString(item.item_id) || null,
|
|
204
|
+
// 1: item_id
|
|
205
|
+
normalizeScalarString(item.item_title) || null,
|
|
206
|
+
// 2: item_title
|
|
207
|
+
toOptionalNumber(item.item_amount),
|
|
208
|
+
// 3: item_amount
|
|
209
|
+
toOptionalNumber(item.item_price),
|
|
210
|
+
// 4: item_price
|
|
211
|
+
normalizeScalarString(item.item_kit_id) || null,
|
|
212
|
+
// 5: item_kit_id
|
|
213
|
+
normalizeScalarString(item.store_id) || null,
|
|
214
|
+
// 6: store_id
|
|
215
|
+
normalizeScalarString(item.order_id) || detailOrderId,
|
|
216
|
+
// 7: order_id
|
|
217
|
+
normalizeFeesAddedInPublication(item.fees_added_in_publication)
|
|
218
|
+
// 8: fees_added_in_publication
|
|
219
|
+
];
|
|
220
|
+
}
|
|
221
|
+
async function meliGetBillingProvisionsByOrderHandler(params) {
|
|
222
|
+
try {
|
|
223
|
+
const profileResolution = await resolveMercadoLibreProfileOrSelection(params.profileId);
|
|
224
|
+
if (!profileResolution.ok) {
|
|
225
|
+
return profileResolution.response;
|
|
226
|
+
}
|
|
227
|
+
const profileId = profileResolution.value.profileId;
|
|
228
|
+
const result = await getMercadoLibreBillingProvisionsByOrder(profileId, {
|
|
229
|
+
orderIds: params.orderIds
|
|
230
|
+
});
|
|
231
|
+
const orderRows = [];
|
|
232
|
+
const paymentRows = [];
|
|
233
|
+
const detailRows = [];
|
|
234
|
+
const salesRows = [];
|
|
235
|
+
const itemsRows = [];
|
|
236
|
+
for (const row of result.results) {
|
|
237
|
+
const projectedOrder = projectOrderRow(row);
|
|
238
|
+
const orderId = normalizeScalarString(projectedOrder[0]) || null;
|
|
239
|
+
const fallbackCurrencyId = normalizeScalarString(projectedOrder[5]) || null;
|
|
240
|
+
orderRows.push(projectedOrder);
|
|
241
|
+
const paymentInfoRows = asRecordArray(row.payment_info);
|
|
242
|
+
for (const paymentInfo of paymentInfoRows) {
|
|
243
|
+
paymentRows.push(projectPaymentRow(orderId, paymentInfo));
|
|
244
|
+
}
|
|
245
|
+
const details = asRecordArray(row.details);
|
|
246
|
+
for (const detail of details) {
|
|
247
|
+
const chargeInfo = asRecord(detail.charge_info);
|
|
248
|
+
const detailId = normalizeScalarString(chargeInfo.detail_id ?? detail.detail_id) || null;
|
|
249
|
+
const detailOrderId = resolveDetailOrderId(detail, orderId);
|
|
250
|
+
detailRows.push(projectDetailRow(orderId, detail, fallbackCurrencyId));
|
|
251
|
+
const detailSales = asRecordArray(detail.sales_info ?? detail.details_sales);
|
|
252
|
+
for (const ds of detailSales) {
|
|
253
|
+
salesRows.push(projectSalesRow(detailId, ds));
|
|
254
|
+
}
|
|
255
|
+
const detailItems = asRecordArray(detail.items_info ?? detail.details_items);
|
|
256
|
+
for (const di of detailItems) {
|
|
257
|
+
itemsRows.push(projectItemsRow(detailId, detailOrderId, di));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const saleFeeNote = "sale_fee may be null for some orders depending on how Mercado Libre settles the billing provision. Preserve it as nullable in downstream analysis.";
|
|
262
|
+
const metadata = {
|
|
263
|
+
order_ids_requested: result.order_ids_requested,
|
|
264
|
+
order_ids_found: result.order_ids_found,
|
|
265
|
+
order_ids_not_found: result.order_ids_not_found,
|
|
266
|
+
request_chunks_total: result.chunks_total,
|
|
267
|
+
request_chunks_succeeded: result.chunks_succeeded,
|
|
268
|
+
request_chunks_failed: result.chunks_failed,
|
|
269
|
+
coverage_complete: result.coverage_complete,
|
|
270
|
+
endpoint: "/billing/integration/group/ML/order/details",
|
|
271
|
+
sale_fee_note: saleFeeNote,
|
|
272
|
+
fees_added_in_publication_note: 'items_info.fees_added_in_publication preserves only exact upstream "Si"/"No" values; all other values are null. It represents installments offered in the listing, not buyer-used payment installments or the CVFN financing cost.',
|
|
273
|
+
pack_resolution_note: "This tool operates on order IDs and does not inherit a value across pack members. Consumers must resolve every member order and apply unanimity externally."
|
|
274
|
+
};
|
|
275
|
+
if (result.failures.length > 0) {
|
|
276
|
+
metadata.failures = result.failures;
|
|
277
|
+
}
|
|
278
|
+
const stripped = stripNulls({
|
|
279
|
+
profile_id: profileId,
|
|
280
|
+
endpoint: "/billing/integration/group/ML/order/details",
|
|
281
|
+
metadata
|
|
282
|
+
});
|
|
283
|
+
stripped.orders_schema = ordersSchema;
|
|
284
|
+
stripped.orders = orderRows;
|
|
285
|
+
stripped.payment_info_schema = paymentInfoSchema;
|
|
286
|
+
stripped.payment_info = paymentRows;
|
|
287
|
+
stripped.details_schema = detailsSchema;
|
|
288
|
+
stripped.details = detailRows;
|
|
289
|
+
stripped.details_sales_schema = detailsSalesSchema;
|
|
290
|
+
stripped.details_sales = salesRows;
|
|
291
|
+
stripped.details_items_schema = detailsItemsSchema;
|
|
292
|
+
stripped.details_items = itemsRows;
|
|
293
|
+
const meta = stripped.metadata;
|
|
294
|
+
meta.order_ids_requested = result.order_ids_requested;
|
|
295
|
+
meta.order_ids_found = result.order_ids_found;
|
|
296
|
+
meta.order_ids_not_found = result.order_ids_not_found;
|
|
297
|
+
return object(stripped);
|
|
298
|
+
} catch (err) {
|
|
299
|
+
return error(
|
|
300
|
+
formatMercadoLibreError(err, "Failed to get MercadoLibre billing provisions by order")
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
export {
|
|
305
|
+
detailsItemsSchema,
|
|
306
|
+
detailsSalesSchema,
|
|
307
|
+
detailsSchema,
|
|
308
|
+
meliGetBillingProvisionsByOrderHandler,
|
|
309
|
+
meliGetBillingProvisionsByOrderSchema,
|
|
310
|
+
ordersSchema,
|
|
311
|
+
paymentInfoSchema
|
|
312
|
+
};
|
|
313
|
+
//# sourceMappingURL=get-billing-provisions-by-order.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/mercadolibre/get-billing-provisions-by-order.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n formatMercadoLibreError,\n} from \"../../services/mercadolibre/mercadolibre-api.js\";\nimport {\n getMercadoLibreBillingProvisionsByOrder,\n} from \"../../services/mercadolibre/mercadolibre-billing.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport {\n asRecord,\n normalizeScalarString,\n} from \"./helpers.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"./profile-resolution.js\";\n\n// \u2500\u2500 Schema \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const meliGetBillingProvisionsByOrderSchema = z.object({\n profileId: z.string().trim().min(1).describe(\"Explicit MercadoLibre profile id to use.\"),\n orderIds: z\n .array(z.string().trim().min(1).describe(\"MercadoLibre order id.\"))\n .min(1)\n .describe(\"One or more MercadoLibre order IDs to fetch billing provisions for.\"),\n});\n\n// \u2500\u2500 Compact schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Top-level order info returned by the official by-order endpoint. */\nexport const ordersSchema = [\n \"order_id\",\n \"sale_fee\",\n \"payment_info_count\",\n \"detail_count\",\n \"document_id\",\n \"currency_id\",\n \"marketplace\",\n] as const;\n\n/** Payment info per order. */\nexport const paymentInfoSchema = [\n \"order_id\",\n \"payment_id\",\n \"payment_type\",\n \"payment_method_id\",\n \"installments\",\n \"transaction_amount\",\n \"total_paid_amount\",\n \"shipping_cost\",\n \"coupon_amount\",\n \"status\",\n \"status_detail\",\n] as const;\n\n/** Detail-level charges within an order. */\nexport const detailsSchema = [\n \"order_id\",\n \"detail_id\",\n \"detail_type\",\n \"detail_sub_type\",\n \"transaction_detail\",\n \"detail_amount\",\n \"currency_id\",\n \"concept_type\",\n \"operation_id\",\n \"shipping_id\",\n \"pack_id\",\n \"inventory_id\",\n] as const;\n\n/** Sales info within details (multiplicity). */\nexport const detailsSalesSchema = [\n \"detail_id\",\n \"order_id\",\n \"operation_id\",\n \"sale_date_time\",\n \"payer_nickname\",\n \"transaction_amount\",\n] as const;\n\n/** Items info within details (multiplicity). */\nexport const detailsItemsSchema = [\n \"detail_id\",\n \"item_id\",\n \"item_title\",\n \"item_amount\",\n \"item_price\",\n \"item_kit_id\",\n \"store_id\",\n \"order_id\",\n \"fees_added_in_publication\",\n] as const;\n\n// \u2500\u2500 Row projectors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype OrderRow = (string | number | null)[];\ntype PaymentRow = (string | number | null)[];\ntype DetailRow = (string | number | null)[];\ntype SalesRow = (string | number | null)[];\ntype ItemsRow = (string | number | null)[];\n\nfunction asRecordArray(value: unknown): Record<string, unknown>[] {\n if (Array.isArray(value)) {\n return value.filter(\n (entry): entry is Record<string, unknown> =>\n entry != null && typeof entry === \"object\" && !Array.isArray(entry)\n ) as Record<string, unknown>[];\n }\n\n const record = asRecord(value);\n return Object.keys(record).length > 0 ? [record] : [];\n}\n\nfunction toOptionalNumber(value: unknown): number | null {\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? value : null;\n }\n\n if (typeof value !== \"string\" || value.trim() === \"\") {\n return null;\n }\n\n const numericValue = Number(value);\n return Number.isFinite(numericValue) ? numericValue : null;\n}\n\nfunction normalizeFeesAddedInPublication(value: unknown): \"Si\" | \"No\" | null {\n return value === \"Si\" || value === \"No\" ? value : null;\n}\n\nfunction resolveDetailOrderId(\n detail: Record<string, unknown>,\n fallbackOrderId: string | null\n): string | null {\n const salesInfo = asRecordArray(detail.sales_info ?? detail.details_sales);\n return (\n normalizeScalarString(salesInfo[0]?.order_id) ||\n normalizeScalarString(detail.order_id) ||\n fallbackOrderId\n );\n}\n\nfunction projectOrderRow(row: Record<string, unknown>): OrderRow {\n const paymentInfo = asRecordArray(row.payment_info);\n const details = asRecordArray(row.details);\n const firstDetail = details[0] ?? {};\n const orderId =\n normalizeScalarString(row.order_id) ||\n normalizeScalarString(paymentInfo[0]?.order_id) ||\n normalizeScalarString(firstDetail.order_id) ||\n resolveDetailOrderId(firstDetail, null) ||\n null;\n const documentInfo = asRecord(row.document_info);\n const currencyInfo = asRecord(row.currency_info);\n const marketplaceInfo = asRecord(row.marketplace_info);\n\n return [\n orderId, // 0: order_id\n toOptionalNumber(row.sale_fee), // 1: sale_fee\n paymentInfo.length, // 2: payment_info_count\n details.length, // 3: detail_count\n normalizeScalarString(documentInfo.document_id ?? row.document_id) || null, // 4: document_id\n normalizeScalarString(currencyInfo.currency_id ?? row.currency_id) || null, // 5: currency_id\n normalizeScalarString(marketplaceInfo.marketplace ?? row.marketplace) || null, // 6: marketplace\n ];\n}\n\nfunction projectPaymentRow(orderId: string | null, payment: Record<string, unknown>): PaymentRow {\n return [\n orderId, // 0: order_id\n normalizeScalarString(payment.payment_id ?? payment.id) || null, // 1: payment_id\n normalizeScalarString(payment.payment_type) || null, // 2: payment_type\n normalizeScalarString(payment.payment_method_id) || null, // 3: payment_method_id\n toOptionalNumber(payment.installments), // 4: installments\n toOptionalNumber(payment.transaction_amount), // 5: transaction_amount\n toOptionalNumber(payment.total_paid_amount), // 6: total_paid_amount\n toOptionalNumber(payment.shipping_cost), // 7: shipping_cost\n toOptionalNumber(payment.coupon_amount), // 8: coupon_amount\n normalizeScalarString(payment.status) || null, // 9: status\n normalizeScalarString(payment.status_detail) || null, // 10: status_detail\n ];\n}\n\nfunction projectDetailRow(\n orderId: string | null,\n detail: Record<string, unknown>,\n fallbackCurrencyId: string | null\n): DetailRow {\n const chargeInfo = asRecord(detail.charge_info);\n const currencyInfo = asRecord(detail.currency_info);\n const detailOrderId = resolveDetailOrderId(detail, orderId);\n const detailAmount = chargeInfo.detail_amount ?? detail.detail_amount;\n\n return [\n detailOrderId, // 0: order_id\n normalizeScalarString(chargeInfo.detail_id ?? detail.detail_id) || null, // 1: detail_id\n normalizeScalarString(chargeInfo.detail_type ?? detail.detail_type) || null, // 2: detail_type\n normalizeScalarString(chargeInfo.detail_sub_type ?? detail.detail_sub_type) || null, // 3: detail_sub_type\n normalizeScalarString(chargeInfo.transaction_detail ?? detail.transaction_detail) || null, // 4: transaction_detail\n toOptionalNumber(detailAmount), // 5: detail_amount\n normalizeScalarString(currencyInfo.currency_id ?? detail.currency_id) || fallbackCurrencyId, // 6: currency_id\n normalizeScalarString(chargeInfo.concept_type ?? detail.concept_type) || null, // 7: concept_type\n normalizeScalarString(chargeInfo.operation_id ?? detail.operation_id) || null, // 8: operation_id\n normalizeScalarString(chargeInfo.shipping_id ?? detail.shipping_id) || null, // 9: shipping_id\n normalizeScalarString(chargeInfo.pack_id ?? detail.pack_id) || null, // 10: pack_id\n normalizeScalarString(chargeInfo.inventory_id ?? detail.inventory_id) || null, // 11: inventory_id\n ];\n}\n\nfunction projectSalesRow(detailId: string | null, sale: Record<string, unknown>): SalesRow {\n return [\n detailId, // 0: detail_id\n normalizeScalarString(sale.order_id) || null, // 1: order_id\n normalizeScalarString(sale.operation_id) || null, // 2: operation_id\n normalizeScalarString(sale.sale_date_time) || null, // 3: sale_date_time\n null, // 4: payer_nickname (redacted)\n toOptionalNumber(sale.transaction_amount), // 5: transaction_amount\n ];\n}\n\nfunction projectItemsRow(\n detailId: string | null,\n detailOrderId: string | null,\n item: Record<string, unknown>\n): ItemsRow {\n return [\n detailId, // 0: detail_id\n normalizeScalarString(item.item_id) || null, // 1: item_id\n normalizeScalarString(item.item_title) || null, // 2: item_title\n toOptionalNumber(item.item_amount), // 3: item_amount\n toOptionalNumber(item.item_price), // 4: item_price\n normalizeScalarString(item.item_kit_id) || null, // 5: item_kit_id\n normalizeScalarString(item.store_id) || null, // 6: store_id\n normalizeScalarString(item.order_id) || detailOrderId, // 7: order_id\n normalizeFeesAddedInPublication(item.fees_added_in_publication), // 8: fees_added_in_publication\n ];\n}\n\n// \u2500\u2500 Handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function meliGetBillingProvisionsByOrderHandler(\n params: z.infer<typeof meliGetBillingProvisionsByOrderSchema>\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 const result = await getMercadoLibreBillingProvisionsByOrder(profileId, {\n orderIds: params.orderIds,\n });\n\n // \u2500\u2500 Accumulate compact rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const orderRows: OrderRow[] = [];\n const paymentRows: PaymentRow[] = [];\n const detailRows: DetailRow[] = [];\n const salesRows: SalesRow[] = [];\n const itemsRows: ItemsRow[] = [];\n\n for (const row of result.results) {\n const projectedOrder = projectOrderRow(row);\n const orderId = normalizeScalarString(projectedOrder[0]) || null;\n const fallbackCurrencyId = normalizeScalarString(projectedOrder[5]) || null;\n\n // \u2500\u2500 Order row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n orderRows.push(projectedOrder);\n\n // \u2500\u2500 Payment info rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const paymentInfoRows = asRecordArray(row.payment_info);\n for (const paymentInfo of paymentInfoRows) {\n paymentRows.push(projectPaymentRow(orderId, paymentInfo));\n }\n\n // \u2500\u2500 Details + secondary blocks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const details = asRecordArray(row.details);\n for (const detail of details) {\n const chargeInfo = asRecord(detail.charge_info);\n const detailId = normalizeScalarString(chargeInfo.detail_id ?? detail.detail_id) || null;\n const detailOrderId = resolveDetailOrderId(detail, orderId);\n detailRows.push(projectDetailRow(orderId, detail, fallbackCurrencyId));\n\n // \u2500\u2500 Details sales \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const detailSales = asRecordArray(detail.sales_info ?? detail.details_sales);\n for (const ds of detailSales) {\n salesRows.push(projectSalesRow(detailId, ds));\n }\n\n // \u2500\u2500 Details items \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const detailItems = asRecordArray(detail.items_info ?? detail.details_items);\n for (const di of detailItems) {\n itemsRows.push(projectItemsRow(detailId, detailOrderId, di));\n }\n }\n }\n\n // \u2500\u2500 Build metadata \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saleFeeNote =\n \"sale_fee may be null for some orders depending on how Mercado Libre settles the billing provision. \" +\n \"Preserve it as nullable in downstream analysis.\";\n\n const metadata: Record<string, unknown> = {\n order_ids_requested: result.order_ids_requested,\n order_ids_found: result.order_ids_found,\n order_ids_not_found: result.order_ids_not_found,\n request_chunks_total: result.chunks_total,\n request_chunks_succeeded: result.chunks_succeeded,\n request_chunks_failed: result.chunks_failed,\n coverage_complete: result.coverage_complete,\n endpoint: \"/billing/integration/group/ML/order/details\",\n sale_fee_note: saleFeeNote,\n fees_added_in_publication_note:\n 'items_info.fees_added_in_publication preserves only exact upstream \"Si\"/\"No\" values; all other values are null. ' +\n \"It represents installments offered in the listing, not buyer-used payment installments or the CVFN financing cost.\",\n pack_resolution_note:\n \"This tool operates on order IDs and does not inherit a value across pack members. Consumers must resolve every member order and apply unanimity externally.\",\n };\n\n if (result.failures.length > 0) {\n metadata.failures = result.failures;\n }\n\n // Build response \u2014 stripNulls top-level, then add back compact arrays\n const stripped = stripNulls({\n profile_id: profileId,\n endpoint: \"/billing/integration/group/ML/order/details\",\n metadata,\n }) as Record<string, unknown>;\n\n // Always attach compact blocks (preserve positional contract)\n stripped.orders_schema = ordersSchema;\n stripped.orders = orderRows;\n stripped.payment_info_schema = paymentInfoSchema;\n stripped.payment_info = paymentRows;\n stripped.details_schema = detailsSchema;\n stripped.details = detailRows;\n stripped.details_sales_schema = detailsSalesSchema;\n stripped.details_sales = salesRows;\n stripped.details_items_schema = detailsItemsSchema;\n stripped.details_items = itemsRows;\n\n // Ensure metadata arrays survive stripNulls\n const meta = stripped.metadata as Record<string, unknown>;\n meta.order_ids_requested = result.order_ids_requested;\n meta.order_ids_found = result.order_ids_found;\n meta.order_ids_not_found = result.order_ids_not_found;\n\n return object(stripped);\n } catch (err) {\n return error(\n formatMercadoLibreError(err, \"Failed to get MercadoLibre billing provisions by order\")\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,6CAA6C;AAI/C,MAAM,wCAAwC,EAAE,OAAO;AAAA,EAC5D,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EACvF,UAAU,EACP,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,wBAAwB,CAAC,EACjE,IAAI,CAAC,EACL,SAAS,qEAAqE;AACnF,CAAC;AAKM,MAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,MAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,MAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,MAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,MAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUA,SAAS,cAAc,OAA2C;AAChE,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM;AAAA,MACX,CAAC,UACC,SAAS,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAAA,IACtE;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,KAAK;AAC7B,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC;AACtD;AAEA,SAAS,iBAAiB,OAA+B;AACvD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC1C;AAEA,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,OAAO,KAAK;AACjC,SAAO,OAAO,SAAS,YAAY,IAAI,eAAe;AACxD;AAEA,SAAS,gCAAgC,OAAoC;AAC3E,SAAO,UAAU,QAAQ,UAAU,OAAO,QAAQ;AACpD;AAEA,SAAS,qBACP,QACA,iBACe;AACf,QAAM,YAAY,cAAc,OAAO,cAAc,OAAO,aAAa;AACzE,SACE,sBAAsB,UAAU,CAAC,GAAG,QAAQ,KAC5C,sBAAsB,OAAO,QAAQ,KACrC;AAEJ;AAEA,SAAS,gBAAgB,KAAwC;AAC/D,QAAM,cAAc,cAAc,IAAI,YAAY;AAClD,QAAM,UAAU,cAAc,IAAI,OAAO;AACzC,QAAM,cAAc,QAAQ,CAAC,KAAK,CAAC;AACnC,QAAM,UACJ,sBAAsB,IAAI,QAAQ,KAClC,sBAAsB,YAAY,CAAC,GAAG,QAAQ,KAC9C,sBAAsB,YAAY,QAAQ,KAC1C,qBAAqB,aAAa,IAAI,KACtC;AACF,QAAM,eAAe,SAAS,IAAI,aAAa;AAC/C,QAAM,eAAe,SAAS,IAAI,aAAa;AAC/C,QAAM,kBAAkB,SAAS,IAAI,gBAAgB;AAErD,SAAO;AAAA,IACL;AAAA;AAAA,IACA,iBAAiB,IAAI,QAAQ;AAAA;AAAA,IAC7B,YAAY;AAAA;AAAA,IACZ,QAAQ;AAAA;AAAA,IACR,sBAAsB,aAAa,eAAe,IAAI,WAAW,KAAK;AAAA;AAAA,IACtE,sBAAsB,aAAa,eAAe,IAAI,WAAW,KAAK;AAAA;AAAA,IACtE,sBAAsB,gBAAgB,eAAe,IAAI,WAAW,KAAK;AAAA;AAAA,EAC3E;AACF;AAEA,SAAS,kBAAkB,SAAwB,SAA8C;AAC/F,SAAO;AAAA,IACL;AAAA;AAAA,IACA,sBAAsB,QAAQ,cAAc,QAAQ,EAAE,KAAK;AAAA;AAAA,IAC3D,sBAAsB,QAAQ,YAAY,KAAK;AAAA;AAAA,IAC/C,sBAAsB,QAAQ,iBAAiB,KAAK;AAAA;AAAA,IACpD,iBAAiB,QAAQ,YAAY;AAAA;AAAA,IACrC,iBAAiB,QAAQ,kBAAkB;AAAA;AAAA,IAC3C,iBAAiB,QAAQ,iBAAiB;AAAA;AAAA,IAC1C,iBAAiB,QAAQ,aAAa;AAAA;AAAA,IACtC,iBAAiB,QAAQ,aAAa;AAAA;AAAA,IACtC,sBAAsB,QAAQ,MAAM,KAAK;AAAA;AAAA,IACzC,sBAAsB,QAAQ,aAAa,KAAK;AAAA;AAAA,EAClD;AACF;AAEA,SAAS,iBACP,SACA,QACA,oBACW;AACX,QAAM,aAAa,SAAS,OAAO,WAAW;AAC9C,QAAM,eAAe,SAAS,OAAO,aAAa;AAClD,QAAM,gBAAgB,qBAAqB,QAAQ,OAAO;AAC1D,QAAM,eAAe,WAAW,iBAAiB,OAAO;AAExD,SAAO;AAAA,IACL;AAAA;AAAA,IACA,sBAAsB,WAAW,aAAa,OAAO,SAAS,KAAK;AAAA;AAAA,IACnE,sBAAsB,WAAW,eAAe,OAAO,WAAW,KAAK;AAAA;AAAA,IACvE,sBAAsB,WAAW,mBAAmB,OAAO,eAAe,KAAK;AAAA;AAAA,IAC/E,sBAAsB,WAAW,sBAAsB,OAAO,kBAAkB,KAAK;AAAA;AAAA,IACrF,iBAAiB,YAAY;AAAA;AAAA,IAC7B,sBAAsB,aAAa,eAAe,OAAO,WAAW,KAAK;AAAA;AAAA,IACzE,sBAAsB,WAAW,gBAAgB,OAAO,YAAY,KAAK;AAAA;AAAA,IACzE,sBAAsB,WAAW,gBAAgB,OAAO,YAAY,KAAK;AAAA;AAAA,IACzE,sBAAsB,WAAW,eAAe,OAAO,WAAW,KAAK;AAAA;AAAA,IACvE,sBAAsB,WAAW,WAAW,OAAO,OAAO,KAAK;AAAA;AAAA,IAC/D,sBAAsB,WAAW,gBAAgB,OAAO,YAAY,KAAK;AAAA;AAAA,EAC3E;AACF;AAEA,SAAS,gBAAgB,UAAyB,MAAyC;AACzF,SAAO;AAAA,IACL;AAAA;AAAA,IACA,sBAAsB,KAAK,QAAQ,KAAK;AAAA;AAAA,IACxC,sBAAsB,KAAK,YAAY,KAAK;AAAA;AAAA,IAC5C,sBAAsB,KAAK,cAAc,KAAK;AAAA;AAAA,IAC9C;AAAA;AAAA,IACA,iBAAiB,KAAK,kBAAkB;AAAA;AAAA,EAC1C;AACF;AAEA,SAAS,gBACP,UACA,eACA,MACU;AACV,SAAO;AAAA,IACL;AAAA;AAAA,IACA,sBAAsB,KAAK,OAAO,KAAK;AAAA;AAAA,IACvC,sBAAsB,KAAK,UAAU,KAAK;AAAA;AAAA,IAC1C,iBAAiB,KAAK,WAAW;AAAA;AAAA,IACjC,iBAAiB,KAAK,UAAU;AAAA;AAAA,IAChC,sBAAsB,KAAK,WAAW,KAAK;AAAA;AAAA,IAC3C,sBAAsB,KAAK,QAAQ,KAAK;AAAA;AAAA,IACxC,sBAAsB,KAAK,QAAQ,KAAK;AAAA;AAAA,IACxC,gCAAgC,KAAK,yBAAyB;AAAA;AAAA,EAChE;AACF;AAIA,eAAsB,uCACpB,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,UAAM,SAAS,MAAM,wCAAwC,WAAW;AAAA,MACtE,UAAU,OAAO;AAAA,IACnB,CAAC;AAID,UAAM,YAAwB,CAAC;AAC/B,UAAM,cAA4B,CAAC;AACnC,UAAM,aAA0B,CAAC;AACjC,UAAM,YAAwB,CAAC;AAC/B,UAAM,YAAwB,CAAC;AAE/B,eAAW,OAAO,OAAO,SAAS;AAChC,YAAM,iBAAiB,gBAAgB,GAAG;AAC1C,YAAM,UAAU,sBAAsB,eAAe,CAAC,CAAC,KAAK;AAC5D,YAAM,qBAAqB,sBAAsB,eAAe,CAAC,CAAC,KAAK;AAGvE,gBAAU,KAAK,cAAc;AAG7B,YAAM,kBAAkB,cAAc,IAAI,YAAY;AACtD,iBAAW,eAAe,iBAAiB;AACzC,oBAAY,KAAK,kBAAkB,SAAS,WAAW,CAAC;AAAA,MAC1D;AAGA,YAAM,UAAU,cAAc,IAAI,OAAO;AACzC,iBAAW,UAAU,SAAS;AAC5B,cAAM,aAAa,SAAS,OAAO,WAAW;AAC9C,cAAM,WAAW,sBAAsB,WAAW,aAAa,OAAO,SAAS,KAAK;AACpF,cAAM,gBAAgB,qBAAqB,QAAQ,OAAO;AAC1D,mBAAW,KAAK,iBAAiB,SAAS,QAAQ,kBAAkB,CAAC;AAGrE,cAAM,cAAc,cAAc,OAAO,cAAc,OAAO,aAAa;AAC3E,mBAAW,MAAM,aAAa;AAC5B,oBAAU,KAAK,gBAAgB,UAAU,EAAE,CAAC;AAAA,QAC9C;AAGA,cAAM,cAAc,cAAc,OAAO,cAAc,OAAO,aAAa;AAC3E,mBAAW,MAAM,aAAa;AAC5B,oBAAU,KAAK,gBAAgB,UAAU,eAAe,EAAE,CAAC;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAIA,UAAM,cACJ;AAGF,UAAM,WAAoC;AAAA,MACxC,qBAAqB,OAAO;AAAA,MAC5B,iBAAiB,OAAO;AAAA,MACxB,qBAAqB,OAAO;AAAA,MAC5B,sBAAsB,OAAO;AAAA,MAC7B,0BAA0B,OAAO;AAAA,MACjC,uBAAuB,OAAO;AAAA,MAC9B,mBAAmB,OAAO;AAAA,MAC1B,UAAU;AAAA,MACV,eAAe;AAAA,MACf,gCACE;AAAA,MAEF,sBACE;AAAA,IACJ;AAEA,QAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,eAAS,WAAW,OAAO;AAAA,IAC7B;AAGA,UAAM,WAAW,WAAW;AAAA,MAC1B,YAAY;AAAA,MACZ,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAGD,aAAS,gBAAgB;AACzB,aAAS,SAAS;AAClB,aAAS,sBAAsB;AAC/B,aAAS,eAAe;AACxB,aAAS,iBAAiB;AAC1B,aAAS,UAAU;AACnB,aAAS,uBAAuB;AAChC,aAAS,gBAAgB;AACzB,aAAS,uBAAuB;AAChC,aAAS,gBAAgB;AAGzB,UAAM,OAAO,SAAS;AACtB,SAAK,sBAAsB,OAAO;AAClC,SAAK,kBAAkB,OAAO;AAC9B,SAAK,sBAAsB,OAAO;AAElC,WAAO,OAAO,QAAQ;AAAA,EACxB,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,wBAAwB,KAAK,wDAAwD;AAAA,IACvF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|