@yoryoboy/bi-mcp 1.19.0 → 1.20.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/mcp-use.json +6 -3
- package/dist/scripts/profile-mercadolibre-billing.js +634 -0
- package/dist/scripts/profile-mercadolibre-billing.js.map +7 -0
- package/dist/src/config/__tests__/tiendanube-profile-store.test.js +50 -0
- package/dist/src/config/__tests__/tiendanube-profile-store.test.js.map +7 -0
- package/dist/src/config/tiendanube-profile-store.js +31 -0
- package/dist/src/config/tiendanube-profile-store.js.map +7 -0
- package/dist/src/google-ads/report-utils.js +78 -0
- package/dist/src/google-ads/report-utils.js.map +7 -0
- package/dist/src/search-console/search-console-utils.js +275 -0
- package/dist/src/search-console/search-console-utils.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report-ventas.test.js +358 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report-ventas.test.js.map +7 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report.test.js +96 -0
- package/dist/src/services/mercadolibre/__tests__/mercadolibre-sales-report.test.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-claim-return-lookup.js +15 -0
- package/dist/src/services/mercadolibre/mercadolibre-claim-return-lookup.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-observability.js +12 -0
- package/dist/src/services/mercadolibre/mercadolibre-observability.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-sale-reference.js +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-sale-reference.js.map +7 -0
- package/dist/src/services/mercadolibre/mercadolibre-sales-report.js +553 -0
- package/dist/src/services/mercadolibre/mercadolibre-sales-report.js.map +7 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js +165 -0
- package/dist/src/services/vtex/__tests__/vtex-catalog-write-batch.test.js.map +7 -0
- package/dist/src/tools/config/__tests__/list-profiles.test.js +144 -1
- package/dist/src/tools/config/__tests__/list-profiles.test.js.map +2 -2
- package/dist/src/tools/config/list-profiles.js +50 -6
- package/dist/src/tools/config/list-profiles.js.map +2 -2
- package/dist/src/tools/mercadolibre/__tests__/get-sales-report-foundation.test.js +417 -0
- package/dist/src/tools/mercadolibre/__tests__/get-sales-report-foundation.test.js.map +7 -0
- package/dist/src/tools/mercadolibre/get-sales-report.js +474 -0
- package/dist/src/tools/mercadolibre/get-sales-report.js.map +7 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js +233 -0
- package/dist/src/tools/vtex/__tests__/catalog-admin-batch.test.js.map +7 -0
- package/dist/src/tools/vtex/catalog-admin-batch.js +298 -0
- package/dist/src/tools/vtex/catalog-admin-batch.js.map +7 -0
- package/dist/tests/meli/meli-sales-report-buyers-mcp-e2e.test.js +137 -0
- package/dist/tests/meli/meli-sales-report-buyers-mcp-e2e.test.js.map +7 -0
- package/dist/tests/meli/meli-sales-report-mcp-e2e-server.js +24 -0
- package/dist/tests/meli/meli-sales-report-mcp-e2e-server.js.map +7 -0
- package/dist/tests/meli/meli-sales-report-mcp-e2e.test.js +207 -0
- package/dist/tests/meli/meli-sales-report-mcp-e2e.test.js.map +7 -0
- package/dist/tests/meli/meli-sales-report-public-mcp-e2e-server.js +10 -0
- package/dist/tests/meli/meli-sales-report-public-mcp-e2e-server.js.map +7 -0
- package/dist/tests/meli/meli-sales-report-public-registration.test.js +98 -0
- package/dist/tests/meli/meli-sales-report-public-registration.test.js.map +7 -0
- package/dist/tests/smoke/process-harness.js +89 -0
- package/dist/tests/smoke/process-harness.js.map +7 -0
- package/dist/tests/smoke/process-harness.test.js +39 -0
- package/dist/tests/smoke/process-harness.test.js.map +7 -0
- package/package.json +1 -1
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
import { listMercadoLibreConnections } from "../../config/mercadolibre-profile-store.js";
|
|
9
9
|
import { listProfileMetaMappings } from "../../config/meta-store.js";
|
|
10
10
|
import { listProfiles } from "../../config/profile-store.js";
|
|
11
|
+
import {
|
|
12
|
+
listTiendanubeConnections
|
|
13
|
+
} from "../../config/tiendanube-profile-store.js";
|
|
11
14
|
import { listVtexConnections } from "../../config/vtex-profile-store.js";
|
|
12
15
|
const listProfilesSchema = z.object({});
|
|
13
16
|
const REQUIRED_GTM_SCOPES = [
|
|
@@ -19,6 +22,25 @@ const REQUIRED_GTM_SCOPES = [
|
|
|
19
22
|
"https://www.googleapis.com/auth/tagmanager.publish",
|
|
20
23
|
"https://www.googleapis.com/auth/tagmanager.readonly"
|
|
21
24
|
];
|
|
25
|
+
const TIENDANUBE_CAPABILITIES = {
|
|
26
|
+
connection_reporting: true,
|
|
27
|
+
operational_tools: "external_mcp",
|
|
28
|
+
provider_surface: "provisional"
|
|
29
|
+
};
|
|
30
|
+
function sanitizePublicStoreId(storeId) {
|
|
31
|
+
if (!storeId) return null;
|
|
32
|
+
const normalized = storeId.trim();
|
|
33
|
+
if (!normalized || normalized.length > 128 || /[\u0000-\u001f\u007f]/.test(normalized) || /\s/.test(normalized)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
function getTiendanubeValidationStatus(connection) {
|
|
39
|
+
if (!connection) return "not_configured";
|
|
40
|
+
if (connection.status === "pending") return "pending";
|
|
41
|
+
if (!connection.lastValidatedAt) return "not_validated";
|
|
42
|
+
return connection.status === "active" ? "validated" : "failed";
|
|
43
|
+
}
|
|
22
44
|
function getGtmStatus(configured, connection) {
|
|
23
45
|
if (!configured) return "not_configured";
|
|
24
46
|
if (!connection) return "error";
|
|
@@ -48,7 +70,8 @@ async function listProfilesHandler() {
|
|
|
48
70
|
mercadolibreConnections,
|
|
49
71
|
metaMappings,
|
|
50
72
|
gtmMappingSummaries,
|
|
51
|
-
googleOAuthConnection
|
|
73
|
+
googleOAuthConnection,
|
|
74
|
+
tiendanubeConnections
|
|
52
75
|
] = await Promise.all([
|
|
53
76
|
listProfiles({ activeOnly: true }),
|
|
54
77
|
listProfileGoogleServiceMappings(),
|
|
@@ -56,7 +79,8 @@ async function listProfilesHandler() {
|
|
|
56
79
|
listMercadoLibreConnections(),
|
|
57
80
|
listProfileMetaMappings(),
|
|
58
81
|
listActiveProfileGtmMappingSummaries(),
|
|
59
|
-
getGoogleOAuthConnection()
|
|
82
|
+
getGoogleOAuthConnection(),
|
|
83
|
+
listTiendanubeConnections()
|
|
60
84
|
]);
|
|
61
85
|
const mappingsByProfileId = new Map(
|
|
62
86
|
mappings.map((mapping) => [mapping.profileId, mapping])
|
|
@@ -79,6 +103,12 @@ async function listProfilesHandler() {
|
|
|
79
103
|
summary.activeMappingCount
|
|
80
104
|
])
|
|
81
105
|
);
|
|
106
|
+
const tiendanubeByProfileId = new Map(
|
|
107
|
+
tiendanubeConnections.map((connection) => [
|
|
108
|
+
connection.profileId,
|
|
109
|
+
connection
|
|
110
|
+
])
|
|
111
|
+
);
|
|
82
112
|
return object({
|
|
83
113
|
total_profiles: profiles.length,
|
|
84
114
|
profiles: profiles.map((profile) => {
|
|
@@ -86,6 +116,7 @@ async function listProfilesHandler() {
|
|
|
86
116
|
const vtexConnection = vtexByProfileId.get(profile.id);
|
|
87
117
|
const mercadolibreConnection = mercadolibreByProfileId.get(profile.id);
|
|
88
118
|
const metaMapping = metaByProfileId.get(profile.id);
|
|
119
|
+
const tiendanubeConnection = tiendanubeByProfileId.get(profile.id);
|
|
89
120
|
const metaConfigured = Boolean(
|
|
90
121
|
metaMapping?.metaBusinessId && metaMapping.status === "active"
|
|
91
122
|
);
|
|
@@ -133,15 +164,28 @@ async function listProfilesHandler() {
|
|
|
133
164
|
configured: metaConfigured,
|
|
134
165
|
status: metaConfigured ? metaMapping?.status ?? "not_configured" : "not_configured",
|
|
135
166
|
raw_status: metaMapping?.status ?? null
|
|
167
|
+
},
|
|
168
|
+
tiendanube: {
|
|
169
|
+
available: true,
|
|
170
|
+
external_mcp: true,
|
|
171
|
+
configured: Boolean(tiendanubeConnection),
|
|
172
|
+
status: tiendanubeConnection?.status ?? "not_configured",
|
|
173
|
+
raw_status: tiendanubeConnection?.status ?? null,
|
|
174
|
+
validation_status: getTiendanubeValidationStatus(
|
|
175
|
+
tiendanubeConnection
|
|
176
|
+
),
|
|
177
|
+
last_validated_at: tiendanubeConnection?.lastValidatedAt?.toISOString() ?? null,
|
|
178
|
+
store_id: sanitizePublicStoreId(
|
|
179
|
+
tiendanubeConnection?.storeId
|
|
180
|
+
),
|
|
181
|
+
capabilities: TIENDANUBE_CAPABILITIES
|
|
136
182
|
}
|
|
137
183
|
}
|
|
138
184
|
};
|
|
139
185
|
})
|
|
140
186
|
});
|
|
141
|
-
} catch
|
|
142
|
-
return error(
|
|
143
|
-
err instanceof Error ? err.message : "Failed to list profiles"
|
|
144
|
-
);
|
|
187
|
+
} catch {
|
|
188
|
+
return error("Failed to list profiles");
|
|
145
189
|
}
|
|
146
190
|
}
|
|
147
191
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/config/list-profiles.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\nimport {\n\tgetGoogleOAuthConnection,\n\tlistActiveProfileGtmMappingSummaries,\n\tlistProfileGoogleServiceMappings,\n\ttype GoogleOAuthConnectionRecord,\n} from \"../../config/google-store.js\";\nimport { listMercadoLibreConnections } from \"../../config/mercadolibre-profile-store.js\";\nimport { listProfileMetaMappings } from \"../../config/meta-store.js\";\nimport { listProfiles } from \"../../config/profile-store.js\";\nimport { listVtexConnections } from \"../../config/vtex-profile-store.js\";\n\nexport const listProfilesSchema = z.object({});\n\ntype NormalizedServiceStatus =\n\t| \"active\"\n\t| \"disabled\"\n\t| \"expired\"\n\t| \"error\"\n\t| \"pending\"\n\t| \"not_configured\";\n\nconst REQUIRED_GTM_SCOPES = [\n\t\"https://www.googleapis.com/auth/tagmanager.manage.accounts\",\n\t\"https://www.googleapis.com/auth/tagmanager.edit.containers\",\n\t\"https://www.googleapis.com/auth/tagmanager.delete.containers\",\n\t\"https://www.googleapis.com/auth/tagmanager.edit.containerversions\",\n\t\"https://www.googleapis.com/auth/tagmanager.manage.users\",\n\t\"https://www.googleapis.com/auth/tagmanager.publish\",\n\t\"https://www.googleapis.com/auth/tagmanager.readonly\",\n] as const;\n\nfunction getGtmStatus(\n\tconfigured: boolean,\n\tconnection: GoogleOAuthConnectionRecord | null,\n): NormalizedServiceStatus {\n\tif (!configured) return \"not_configured\";\n\tif (!connection) return \"error\";\n\tif (connection.status !== \"active\") return connection.status;\n\tif (!connection.encryptedRefreshToken) return \"error\";\n\treturn REQUIRED_GTM_SCOPES.every((scope) => connection.scopes.includes(scope))\n\t\t? \"active\"\n\t\t: \"error\";\n}\n\nfunction normalizeVtexStatus(\n\tstatus: \"pending\" | \"valid\" | \"invalid\" | \"disabled\",\n): Exclude<NormalizedServiceStatus, \"expired\" | \"not_configured\"> {\n\tswitch (status) {\n\t\tcase \"valid\":\n\t\t\treturn \"active\";\n\t\tcase \"invalid\":\n\t\t\treturn \"error\";\n\t\tcase \"disabled\":\n\t\t\treturn \"disabled\";\n\t\tcase \"pending\":\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\nexport async function listProfilesHandler() {\n\ttry {\n\t\tconst [\n\t\t\tprofiles,\n\t\t\tmappings,\n\t\t\tvtexConnections,\n\t\t\tmercadolibreConnections,\n\t\t\tmetaMappings,\n\t\t\tgtmMappingSummaries,\n\t\t\tgoogleOAuthConnection,\n\t\t] = await Promise.all([\n\t\t\tlistProfiles({ activeOnly: true }),\n\t\t\tlistProfileGoogleServiceMappings(),\n\t\t\tlistVtexConnections(),\n\t\t\tlistMercadoLibreConnections(),\n\t\t\tlistProfileMetaMappings(),\n\t\t\tlistActiveProfileGtmMappingSummaries(),\n\t\t\tgetGoogleOAuthConnection(),\n\t\t]);\n\t\tconst mappingsByProfileId = new Map(\n\t\t\tmappings.map((mapping) => [mapping.profileId, mapping]),\n\t\t);\n\t\tconst vtexByProfileId = new Map(\n\t\t\tvtexConnections.map((connection) => [connection.profileId, connection]),\n\t\t);\n\t\tconst mercadolibreByProfileId = new Map(\n\t\t\tmercadolibreConnections.map((connection) => [\n\t\t\t\tconnection.profileId,\n\t\t\t\tconnection,\n\t\t\t]),\n\t\t);\n\t\tconst metaByProfileId = new Map(\n\t\t\tmetaMappings.map((mapping) => [mapping.profileId, mapping]),\n\t\t);\n\t\tconst gtmMappingCountByProfileId = new Map(\n\t\t\tgtmMappingSummaries.map((summary) => [\n\t\t\t\tsummary.profileId,\n\t\t\t\tsummary.activeMappingCount,\n\t\t\t]),\n\t\t);\n\t\treturn object({\n\t\t\ttotal_profiles: profiles.length,\n\t\t\tprofiles: profiles.map((profile) => {\n\t\t\t\tconst mapping = mappingsByProfileId.get(profile.id);\n\t\t\t\tconst vtexConnection = vtexByProfileId.get(profile.id);\n\t\t\t\tconst mercadolibreConnection = mercadolibreByProfileId.get(profile.id);\n\t\t\t\tconst metaMapping = metaByProfileId.get(profile.id);\n\t\t\t\tconst metaConfigured = Boolean(\n\t\t\t\t\tmetaMapping?.metaBusinessId && metaMapping.status === \"active\",\n\t\t\t\t);\n\t\t\t\tconst gtmConfigured =\n\t\t\t\t\t(gtmMappingCountByProfileId.get(profile.id) ?? 0) > 0;\n\t\t\t\treturn {\n\t\t\t\t\tprofile_id: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\tis_active: profile.isActive,\n\t\t\t\t\tcreated_at: profile.createdAt.toISOString(),\n\t\t\t\t\tupdated_at: profile.updatedAt.toISOString(),\n\t\t\t\t\tservices: {\n\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\tgoogle_ads: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.googleAdsCustomerId),\n\t\t\t\t\t\t\t\tstatus: mapping?.googleAdsCustomerId\n\t\t\t\t\t\t\t\t\t? mapping.googleAdsStatus\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.googleAdsCustomerId\n\t\t\t\t\t\t\t\t\t? mapping.googleAdsStatus\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tga4: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.ga4PropertyId),\n\t\t\t\t\t\t\t\tstatus: mapping?.ga4PropertyId\n\t\t\t\t\t\t\t\t\t? mapping.ga4Status\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.ga4PropertyId ? mapping.ga4Status : null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tsearch_console: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.searchConsoleSiteUrl),\n\t\t\t\t\t\t\t\tstatus: mapping?.searchConsoleSiteUrl\n\t\t\t\t\t\t\t\t\t? mapping.searchConsoleStatus\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.searchConsoleSiteUrl\n\t\t\t\t\t\t\t\t\t? mapping.searchConsoleStatus\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tgtm: {\n\t\t\t\t\t\t\t\tconfigured: gtmConfigured,\n\t\t\t\t\t\t\t\tstatus: getGtmStatus(gtmConfigured, googleOAuthConnection),\n\t\t\t\t\t\t\t\traw_status: gtmConfigured\n\t\t\t\t\t\t\t\t\t? (googleOAuthConnection?.status ?? null)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvtex: {\n\t\t\t\t\t\t\tconfigured: Boolean(vtexConnection),\n\t\t\t\t\t\t\tstatus: vtexConnection\n\t\t\t\t\t\t\t\t? normalizeVtexStatus(vtexConnection.status)\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: vtexConnection ? vtexConnection.status : null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmercadolibre: {\n\t\t\t\t\t\t\tconfigured: Boolean(mercadolibreConnection),\n\t\t\t\t\t\t\tstatus: mercadolibreConnection\n\t\t\t\t\t\t\t\t? mercadolibreConnection.status\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: mercadolibreConnection\n\t\t\t\t\t\t\t\t? mercadolibreConnection.status\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\tconfigured: metaConfigured,\n\t\t\t\t\t\t\tstatus: metaConfigured\n\t\t\t\t\t\t\t\t? (metaMapping?.status ?? \"not_configured\")\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: metaMapping?.status ?? null,\n\t\t\t\t\t\t},\n\t\t\t\t\t
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAClB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,mCAAmC;AAC5C,SAAS,+BAA+B;AACxC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AAE7B,MAAM,qBAAqB,EAAE,OAAO,CAAC,CAAC;AAU7C,MAAM,sBAAsB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEA,SAAS,aACR,YACA,YAC0B;AAC1B,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,WAAW,WAAW,SAAU,QAAO,WAAW;AACtD,MAAI,CAAC,WAAW,sBAAuB,QAAO;AAC9C,SAAO,oBAAoB,MAAM,CAAC,UAAU,WAAW,OAAO,SAAS,KAAK,CAAC,IAC1E,WACA;AACJ;AAEA,SAAS,oBACR,QACiE;AACjE,UAAQ,QAAQ;AAAA,IACf,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AAAA,IACL;AACC,aAAO;AAAA,EACT;AACD;AAEA,eAAsB,sBAAsB;AAC3C,MAAI;AACH,UAAM;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,IAAI,MAAM,QAAQ,IAAI;AAAA,MACrB,aAAa,EAAE,YAAY,KAAK,CAAC;AAAA,MACjC,iCAAiC;AAAA,MACjC,oBAAoB;AAAA,MACpB,4BAA4B;AAAA,MAC5B,wBAAwB;AAAA,MACxB,qCAAqC;AAAA,MACrC,yBAAyB;AAAA,
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\nimport {\n\tgetGoogleOAuthConnection,\n\tlistActiveProfileGtmMappingSummaries,\n\tlistProfileGoogleServiceMappings,\n\ttype GoogleOAuthConnectionRecord,\n} from \"../../config/google-store.js\";\nimport { listMercadoLibreConnections } from \"../../config/mercadolibre-profile-store.js\";\nimport { listProfileMetaMappings } from \"../../config/meta-store.js\";\nimport { listProfiles } from \"../../config/profile-store.js\";\nimport {\n listTiendanubeConnections,\n type TiendanubeConnectionRecord,\n} from \"../../config/tiendanube-profile-store.js\";\nimport { listVtexConnections } from \"../../config/vtex-profile-store.js\";\n\nexport const listProfilesSchema = z.object({});\n\ntype NormalizedServiceStatus =\n\t| \"active\"\n\t| \"disabled\"\n\t| \"expired\"\n\t| \"error\"\n\t| \"pending\"\n\t| \"not_configured\";\n\nconst REQUIRED_GTM_SCOPES = [\n\t\"https://www.googleapis.com/auth/tagmanager.manage.accounts\",\n\t\"https://www.googleapis.com/auth/tagmanager.edit.containers\",\n\t\"https://www.googleapis.com/auth/tagmanager.delete.containers\",\n\t\"https://www.googleapis.com/auth/tagmanager.edit.containerversions\",\n\t\"https://www.googleapis.com/auth/tagmanager.manage.users\",\n\t\"https://www.googleapis.com/auth/tagmanager.publish\",\n\t\"https://www.googleapis.com/auth/tagmanager.readonly\",\n] as const;\n\nconst TIENDANUBE_CAPABILITIES = {\n\tconnection_reporting: true,\n\toperational_tools: \"external_mcp\",\n\tprovider_surface: \"provisional\",\n} as const;\n\ntype TiendanubeValidationStatus =\n\t| \"validated\"\n\t| \"failed\"\n\t| \"pending\"\n\t| \"not_validated\"\n\t| \"not_configured\";\n\nfunction sanitizePublicStoreId(storeId: string | undefined): string | null {\n\tif (!storeId) return null;\n\n\tconst normalized = storeId.trim();\n\tif (\n\t\t!normalized ||\n\t\tnormalized.length > 128 ||\n\t\t/[\\u0000-\\u001f\\u007f]/.test(normalized) ||\n\t\t/\\s/.test(normalized)\n\t) {\n\t\treturn null;\n\t}\n\n\treturn normalized;\n}\n\nfunction getTiendanubeValidationStatus(\n\tconnection: TiendanubeConnectionRecord | undefined,\n): TiendanubeValidationStatus {\n\tif (!connection) return \"not_configured\";\n\tif (connection.status === \"pending\") return \"pending\";\n\tif (!connection.lastValidatedAt) return \"not_validated\";\n\treturn connection.status === \"active\" ? \"validated\" : \"failed\";\n}\n\nfunction getGtmStatus(\n\tconfigured: boolean,\n\tconnection: GoogleOAuthConnectionRecord | null,\n): NormalizedServiceStatus {\n\tif (!configured) return \"not_configured\";\n\tif (!connection) return \"error\";\n\tif (connection.status !== \"active\") return connection.status;\n\tif (!connection.encryptedRefreshToken) return \"error\";\n\treturn REQUIRED_GTM_SCOPES.every((scope) => connection.scopes.includes(scope))\n\t\t? \"active\"\n\t\t: \"error\";\n}\n\nfunction normalizeVtexStatus(\n\tstatus: \"pending\" | \"valid\" | \"invalid\" | \"disabled\",\n): Exclude<NormalizedServiceStatus, \"expired\" | \"not_configured\"> {\n\tswitch (status) {\n\t\tcase \"valid\":\n\t\t\treturn \"active\";\n\t\tcase \"invalid\":\n\t\t\treturn \"error\";\n\t\tcase \"disabled\":\n\t\t\treturn \"disabled\";\n\t\tcase \"pending\":\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\nexport async function listProfilesHandler() {\n\ttry {\n\t\tconst [\n\t\t\tprofiles,\n\t\t\tmappings,\n\t\t\tvtexConnections,\n\t\t\tmercadolibreConnections,\n\t\t\tmetaMappings,\n\t\t\tgtmMappingSummaries,\n\t\t\tgoogleOAuthConnection,\n\t\t\ttiendanubeConnections,\n\t\t] = await Promise.all([\n\t\t\tlistProfiles({ activeOnly: true }),\n\t\t\tlistProfileGoogleServiceMappings(),\n\t\t\tlistVtexConnections(),\n\t\t\tlistMercadoLibreConnections(),\n\t\t\tlistProfileMetaMappings(),\n\t\t\tlistActiveProfileGtmMappingSummaries(),\n\t\t\tgetGoogleOAuthConnection(),\n\t\t\tlistTiendanubeConnections(),\n\t\t]);\n\t\tconst mappingsByProfileId = new Map(\n\t\t\tmappings.map((mapping) => [mapping.profileId, mapping]),\n\t\t);\n\t\tconst vtexByProfileId = new Map(\n\t\t\tvtexConnections.map((connection) => [connection.profileId, connection]),\n\t\t);\n\t\tconst mercadolibreByProfileId = new Map(\n\t\t\tmercadolibreConnections.map((connection) => [\n\t\t\t\tconnection.profileId,\n\t\t\t\tconnection,\n\t\t\t]),\n\t\t);\n\t\tconst metaByProfileId = new Map(\n\t\t\tmetaMappings.map((mapping) => [mapping.profileId, mapping]),\n\t\t);\n\t\tconst gtmMappingCountByProfileId = new Map(\n\t\t\tgtmMappingSummaries.map((summary) => [\n\t\t\t\tsummary.profileId,\n\t\t\t\tsummary.activeMappingCount,\n\t\t\t]),\n\t\t);\n\t\tconst tiendanubeByProfileId = new Map(\n\t\t\ttiendanubeConnections.map((connection) => [\n\t\t\t\tconnection.profileId,\n\t\t\t\tconnection,\n\t\t\t]),\n\t\t);\n\t\treturn object({\n\t\t\ttotal_profiles: profiles.length,\n\t\t\tprofiles: profiles.map((profile) => {\n\t\t\t\tconst mapping = mappingsByProfileId.get(profile.id);\n\t\t\t\tconst vtexConnection = vtexByProfileId.get(profile.id);\n\t\t\t\tconst mercadolibreConnection = mercadolibreByProfileId.get(profile.id);\n\t\t\t\tconst metaMapping = metaByProfileId.get(profile.id);\n\t\t\t\tconst tiendanubeConnection = tiendanubeByProfileId.get(profile.id);\n\t\t\t\tconst metaConfigured = Boolean(\n\t\t\t\t\tmetaMapping?.metaBusinessId && metaMapping.status === \"active\",\n\t\t\t\t);\n\t\t\t\tconst gtmConfigured =\n\t\t\t\t\t(gtmMappingCountByProfileId.get(profile.id) ?? 0) > 0;\n\t\t\t\treturn {\n\t\t\t\t\tprofile_id: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\tis_active: profile.isActive,\n\t\t\t\t\tcreated_at: profile.createdAt.toISOString(),\n\t\t\t\t\tupdated_at: profile.updatedAt.toISOString(),\n\t\t\t\t\tservices: {\n\t\t\t\t\t\tgoogle: {\n\t\t\t\t\t\t\tgoogle_ads: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.googleAdsCustomerId),\n\t\t\t\t\t\t\t\tstatus: mapping?.googleAdsCustomerId\n\t\t\t\t\t\t\t\t\t? mapping.googleAdsStatus\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.googleAdsCustomerId\n\t\t\t\t\t\t\t\t\t? mapping.googleAdsStatus\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tga4: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.ga4PropertyId),\n\t\t\t\t\t\t\t\tstatus: mapping?.ga4PropertyId\n\t\t\t\t\t\t\t\t\t? mapping.ga4Status\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.ga4PropertyId ? mapping.ga4Status : null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tsearch_console: {\n\t\t\t\t\t\t\t\tconfigured: Boolean(mapping?.searchConsoleSiteUrl),\n\t\t\t\t\t\t\t\tstatus: mapping?.searchConsoleSiteUrl\n\t\t\t\t\t\t\t\t\t? mapping.searchConsoleStatus\n\t\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\t\traw_status: mapping?.searchConsoleSiteUrl\n\t\t\t\t\t\t\t\t\t? mapping.searchConsoleStatus\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tgtm: {\n\t\t\t\t\t\t\t\tconfigured: gtmConfigured,\n\t\t\t\t\t\t\t\tstatus: getGtmStatus(gtmConfigured, googleOAuthConnection),\n\t\t\t\t\t\t\t\traw_status: gtmConfigured\n\t\t\t\t\t\t\t\t\t? (googleOAuthConnection?.status ?? null)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvtex: {\n\t\t\t\t\t\t\tconfigured: Boolean(vtexConnection),\n\t\t\t\t\t\t\tstatus: vtexConnection\n\t\t\t\t\t\t\t\t? normalizeVtexStatus(vtexConnection.status)\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: vtexConnection ? vtexConnection.status : null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmercadolibre: {\n\t\t\t\t\t\t\tconfigured: Boolean(mercadolibreConnection),\n\t\t\t\t\t\t\tstatus: mercadolibreConnection\n\t\t\t\t\t\t\t\t? mercadolibreConnection.status\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: mercadolibreConnection\n\t\t\t\t\t\t\t\t? mercadolibreConnection.status\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\tconfigured: metaConfigured,\n\t\t\t\t\t\t\tstatus: metaConfigured\n\t\t\t\t\t\t\t\t? (metaMapping?.status ?? \"not_configured\")\n\t\t\t\t\t\t\t\t: \"not_configured\",\n\t\t\t\t\t\t\traw_status: metaMapping?.status ?? null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttiendanube: {\n\t\t\t\t\t\t\tavailable: true,\n\t\t\t\t\t\t\texternal_mcp: true,\n\t\t\t\t\t\t\tconfigured: Boolean(tiendanubeConnection),\n\t\t\t\t\t\t\tstatus: tiendanubeConnection?.status ?? \"not_configured\",\n\t\t\t\t\t\t\traw_status: tiendanubeConnection?.status ?? null,\n\t\t\t\t\t\t\tvalidation_status: getTiendanubeValidationStatus(\n\t\t\t\t\t\t\t\ttiendanubeConnection,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tlast_validated_at:\n\t\t\t\t\t\t\t\ttiendanubeConnection?.lastValidatedAt?.toISOString() ?? null,\n\t\t\t\t\t\t\tstore_id: sanitizePublicStoreId(\n\t\t\t\t\t\t\t\ttiendanubeConnection?.storeId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tcapabilities: TIENDANUBE_CAPABILITIES,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t});\n\t} catch {\n\t\treturn error(\"Failed to list profiles\");\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
buildSalesReportDateBoundaries,
|
|
4
|
+
buildSalesReportMetadata,
|
|
5
|
+
createSalesReportPerformanceTracker,
|
|
6
|
+
decodeSalesReportCursor,
|
|
7
|
+
encodeSalesReportCursor,
|
|
8
|
+
getSalesReportOperationSaleTimestamp,
|
|
9
|
+
isSalesReportOperationAfterCursor,
|
|
10
|
+
meliGetSalesReportSchema,
|
|
11
|
+
sortSalesReportOperations
|
|
12
|
+
} from "../get-sales-report.js";
|
|
13
|
+
import {
|
|
14
|
+
buildOrderUniversePagePlan,
|
|
15
|
+
groupMercadoLibreOrders
|
|
16
|
+
} from "../../../services/mercadolibre/mercadolibre-sales-report.js";
|
|
17
|
+
const TEST_KEY = "11".repeat(32);
|
|
18
|
+
function order(orderId, saleDate) {
|
|
19
|
+
return {
|
|
20
|
+
order_id: orderId,
|
|
21
|
+
ventas: {
|
|
22
|
+
fecha_de_venta: saleDate,
|
|
23
|
+
estado: null,
|
|
24
|
+
descripcion_del_estado: null,
|
|
25
|
+
pertenece_a_un_kit: null,
|
|
26
|
+
unidades: null,
|
|
27
|
+
ingresos_por_productos_ars: null,
|
|
28
|
+
orden_de_compra: null
|
|
29
|
+
},
|
|
30
|
+
publicidad: { venta_por_publicidad: null },
|
|
31
|
+
publicaciones: {
|
|
32
|
+
sku: null,
|
|
33
|
+
numero_de_publicacion: null,
|
|
34
|
+
canal_de_venta: null,
|
|
35
|
+
titulo_de_la_publicacion: null,
|
|
36
|
+
variante: null,
|
|
37
|
+
precio_unitario_de_venta_de_la_publicacion_ars: null,
|
|
38
|
+
tiene_cuotas_agregadas: null
|
|
39
|
+
},
|
|
40
|
+
facturacion_al_comprador: {
|
|
41
|
+
factura_adjunta: null,
|
|
42
|
+
datos_personales_o_de_empresa: null,
|
|
43
|
+
tipo_y_numero_de_documento: null,
|
|
44
|
+
direccion: null,
|
|
45
|
+
condicion_fiscal_iva: null,
|
|
46
|
+
numero_iibb: null
|
|
47
|
+
},
|
|
48
|
+
compradores: {
|
|
49
|
+
comprador: null,
|
|
50
|
+
negocio: null,
|
|
51
|
+
dni: null,
|
|
52
|
+
domicilio: null,
|
|
53
|
+
ciudad: null,
|
|
54
|
+
estado: null,
|
|
55
|
+
codigo_postal: null,
|
|
56
|
+
pais: null
|
|
57
|
+
},
|
|
58
|
+
envios: {
|
|
59
|
+
forma_de_entrega: null,
|
|
60
|
+
fecha_en_camino: null,
|
|
61
|
+
fecha_entregado: null,
|
|
62
|
+
transportista: null,
|
|
63
|
+
numero_de_seguimiento: null,
|
|
64
|
+
url_de_seguimiento: null
|
|
65
|
+
},
|
|
66
|
+
devoluciones: {
|
|
67
|
+
unidades: null,
|
|
68
|
+
forma_de_entrega: null,
|
|
69
|
+
fecha_en_camino: null,
|
|
70
|
+
fecha_entregado: null,
|
|
71
|
+
transportista: null,
|
|
72
|
+
numero_de_seguimiento: null,
|
|
73
|
+
url_de_seguimiento: null,
|
|
74
|
+
revisado_por_mercado_libre: null,
|
|
75
|
+
fecha_de_revision: null,
|
|
76
|
+
dinero_a_favor: null,
|
|
77
|
+
resultado: null,
|
|
78
|
+
destino: null,
|
|
79
|
+
motivo_del_resultado: null
|
|
80
|
+
},
|
|
81
|
+
reclamos: {
|
|
82
|
+
unidades: null,
|
|
83
|
+
reclamo_abierto: null,
|
|
84
|
+
reclamo_cerrado: null,
|
|
85
|
+
con_mediacion: null
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function operation(packId, orderId, saleDate) {
|
|
90
|
+
return {
|
|
91
|
+
pack_id: packId,
|
|
92
|
+
ventas: {
|
|
93
|
+
paquete_de_varios_productos: packId !== null,
|
|
94
|
+
cargo_por_venta: null,
|
|
95
|
+
costo_fijo: null,
|
|
96
|
+
costo_por_ofrecer_cuotas: null,
|
|
97
|
+
ingresos_por_envio_ars: null,
|
|
98
|
+
costos_de_envio_ars: null,
|
|
99
|
+
costo_de_envio_por_cambio_de_producto: null,
|
|
100
|
+
costo_de_envio_basado_en_medidas_y_peso_declarados: null,
|
|
101
|
+
cargo_por_diferencias_en_medidas_y_peso_del_paquete: null,
|
|
102
|
+
impuestos: null,
|
|
103
|
+
descuentos_y_bonificaciones: null,
|
|
104
|
+
anulaciones_y_reembolsos_ars: null,
|
|
105
|
+
total_ars: null,
|
|
106
|
+
periodos_de_facturacion: []
|
|
107
|
+
},
|
|
108
|
+
ordenes: [order(orderId, saleDate)]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
describe("meli_get_sales_report Phase 0 foundation", () => {
|
|
112
|
+
const originalKey = process.env.DB_ENCRYPTION_KEY;
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
process.env.DB_ENCRYPTION_KEY = TEST_KEY;
|
|
115
|
+
});
|
|
116
|
+
afterEach(() => {
|
|
117
|
+
if (originalKey === void 0) delete process.env.DB_ENCRYPTION_KEY;
|
|
118
|
+
else process.env.DB_ENCRYPTION_KEY = originalKey;
|
|
119
|
+
});
|
|
120
|
+
it("tracks monotonic stage and total durations deterministically", async () => {
|
|
121
|
+
let currentTime = 100;
|
|
122
|
+
const tracker = createSalesReportPerformanceTracker(() => currentTime);
|
|
123
|
+
const stageStartedAt = tracker.start();
|
|
124
|
+
currentTime = 104.6;
|
|
125
|
+
expect(tracker.finish("seleccion", stageStartedAt)).toBe(5);
|
|
126
|
+
await tracker.measure("postventa", async () => {
|
|
127
|
+
currentTime = 111.2;
|
|
128
|
+
});
|
|
129
|
+
currentTime = 115;
|
|
130
|
+
expect(tracker.duration("seleccion")).toBe(5);
|
|
131
|
+
expect(tracker.duration("postventa")).toBe(7);
|
|
132
|
+
expect(tracker.duration("ausente")).toBe(0);
|
|
133
|
+
expect(tracker.total()).toBe(15);
|
|
134
|
+
});
|
|
135
|
+
it("validates input and applies the default and maximum limits", () => {
|
|
136
|
+
expect(
|
|
137
|
+
meliGetSalesReportSchema.parse({
|
|
138
|
+
profileId: "triplim",
|
|
139
|
+
startDate: "2026-06-01",
|
|
140
|
+
endDate: "2026-06-30"
|
|
141
|
+
}).limit ?? 200
|
|
142
|
+
).toBe(200);
|
|
143
|
+
expect(
|
|
144
|
+
meliGetSalesReportSchema.parse({
|
|
145
|
+
profileId: "triplim",
|
|
146
|
+
startDate: "2026-06-01",
|
|
147
|
+
endDate: "2026-06-30",
|
|
148
|
+
limit: 1e3
|
|
149
|
+
}).limit
|
|
150
|
+
).toBe(1e3);
|
|
151
|
+
expect(
|
|
152
|
+
() => meliGetSalesReportSchema.parse({
|
|
153
|
+
profileId: "triplim",
|
|
154
|
+
startDate: "2026-02-30",
|
|
155
|
+
endDate: "2026-06-30"
|
|
156
|
+
})
|
|
157
|
+
).toThrow();
|
|
158
|
+
expect(
|
|
159
|
+
() => meliGetSalesReportSchema.parse({
|
|
160
|
+
profileId: "triplim",
|
|
161
|
+
startDate: "2026-06-01",
|
|
162
|
+
endDate: "2026-06-30",
|
|
163
|
+
billingPeriod: "2026-06"
|
|
164
|
+
})
|
|
165
|
+
).toThrow();
|
|
166
|
+
expect(
|
|
167
|
+
() => meliGetSalesReportSchema.parse({
|
|
168
|
+
profileId: "triplim",
|
|
169
|
+
startDate: "2026-06-01",
|
|
170
|
+
endDate: "2026-06-30",
|
|
171
|
+
limit: 1001
|
|
172
|
+
})
|
|
173
|
+
).toThrow();
|
|
174
|
+
});
|
|
175
|
+
it("accepts strict range and explicit-order modes with trimmed stable duplicates", () => {
|
|
176
|
+
expect(meliGetSalesReportSchema.parse({
|
|
177
|
+
profileId: "triplim",
|
|
178
|
+
startDate: "2026-06-01",
|
|
179
|
+
endDate: "2026-06-30"
|
|
180
|
+
})).toEqual(expect.objectContaining({ startDate: "2026-06-01", endDate: "2026-06-30" }));
|
|
181
|
+
expect(meliGetSalesReportSchema.parse({
|
|
182
|
+
profileId: "triplim",
|
|
183
|
+
orderIds: [" order-b ", "order-a", "order-b"]
|
|
184
|
+
}).orderIds).toEqual(["order-b", "order-a", "order-b"]);
|
|
185
|
+
});
|
|
186
|
+
it.each([
|
|
187
|
+
{ profileId: "triplim", orderIds: [], label: "empty list" },
|
|
188
|
+
{ profileId: "triplim", orderIds: Array.from({ length: 101 }, (_, index) => `order-${index}`), label: "more than 100 IDs" },
|
|
189
|
+
{ profileId: "triplim", orderIds: [" "], label: "empty item" },
|
|
190
|
+
{ profileId: "triplim", orderIds: ["order-1"], startDate: "2026-06-01", endDate: "2026-06-30", label: "dates in explicit mode" },
|
|
191
|
+
{ profileId: "triplim", orderIds: ["order-1"], limit: 1, label: "limit in explicit mode" },
|
|
192
|
+
{ profileId: "triplim", orderIds: ["order-1"], cursor: "cursor", label: "cursor in explicit mode" },
|
|
193
|
+
{ profileId: "triplim", startDate: "2026-06-01", label: "incomplete range" }
|
|
194
|
+
])("rejects $label", ({ label: _label, ...input }) => {
|
|
195
|
+
expect(() => meliGetSalesReportSchema.parse(input)).toThrow();
|
|
196
|
+
});
|
|
197
|
+
it("rejects reversed sales dates", () => {
|
|
198
|
+
expect(
|
|
199
|
+
() => meliGetSalesReportSchema.parse({
|
|
200
|
+
profileId: "triplim",
|
|
201
|
+
startDate: "2026-07-01",
|
|
202
|
+
endDate: "2026-06-30"
|
|
203
|
+
})
|
|
204
|
+
).toThrow("endDate must be on or after startDate");
|
|
205
|
+
});
|
|
206
|
+
it("builds inclusive Buenos Aires timezone boundaries", () => {
|
|
207
|
+
expect(buildSalesReportDateBoundaries("2026-06-01", "2026-06-30")).toEqual({
|
|
208
|
+
timeZone: "America/Argentina/Buenos_Aires",
|
|
209
|
+
from: "2026-06-01T00:00:00.000-03:00",
|
|
210
|
+
to: "2026-06-30T23:59:59.999-03:00"
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
it("uses the historical Buenos Aires offset for date boundaries", () => {
|
|
214
|
+
expect(buildSalesReportDateBoundaries("2008-01-01", "2008-01-31")).toEqual({
|
|
215
|
+
timeZone: "America/Argentina/Buenos_Aires",
|
|
216
|
+
from: "2008-01-01T00:00:00.000-02:00",
|
|
217
|
+
to: "2008-01-31T23:59:59.999-02:00"
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
it("orders operations by sale date and then operation key descending without mutation", () => {
|
|
221
|
+
const original = [
|
|
222
|
+
operation(null, "200", "2026-06-30T20:00:00-03:00"),
|
|
223
|
+
operation("300", "201", "2026-06-30T20:00:00-03:00"),
|
|
224
|
+
operation(null, "999", "2026-06-29T20:00:00-03:00")
|
|
225
|
+
];
|
|
226
|
+
const sorted = sortSalesReportOperations(original);
|
|
227
|
+
expect(sorted.map((item) => item.pack_id ?? item.ordenes[0].order_id)).toEqual([
|
|
228
|
+
"300",
|
|
229
|
+
"200",
|
|
230
|
+
"999"
|
|
231
|
+
]);
|
|
232
|
+
expect(original[0].ordenes[0].order_id).toBe("200");
|
|
233
|
+
});
|
|
234
|
+
it("chooses the latest sale by instant when timestamps have mixed offsets", () => {
|
|
235
|
+
const packed = operation("300", "201", "2026-06-02T00:30:00-03:00");
|
|
236
|
+
packed.ordenes.push(order("202", "2026-06-02T00:00:00-04:00"));
|
|
237
|
+
expect(getSalesReportOperationSaleTimestamp(packed)).toBe("2026-06-02T00:00:00-04:00");
|
|
238
|
+
});
|
|
239
|
+
it("round-trips a self-contained cursor and rejects scope changes", () => {
|
|
240
|
+
const scope = { profileId: "triplim", startDate: "2026-06-01", endDate: "2026-06-30" };
|
|
241
|
+
const cursor = encodeSalesReportCursor({
|
|
242
|
+
...scope,
|
|
243
|
+
lastSaleTimestamp: "2026-06-20T10:00:00-03:00",
|
|
244
|
+
lastOperationKey: "200001"
|
|
245
|
+
});
|
|
246
|
+
expect(decodeSalesReportCursor(cursor, scope)).toEqual({
|
|
247
|
+
version: 1,
|
|
248
|
+
...scope,
|
|
249
|
+
lastSaleTimestamp: "2026-06-20T10:00:00-03:00",
|
|
250
|
+
lastOperationKey: "200001"
|
|
251
|
+
});
|
|
252
|
+
expect(
|
|
253
|
+
() => decodeSalesReportCursor(cursor, { ...scope, profileId: "another-profile" })
|
|
254
|
+
).toThrow("does not match the requested report scope");
|
|
255
|
+
});
|
|
256
|
+
it("rejects cursor tampering", () => {
|
|
257
|
+
const scope = { profileId: "triplim", startDate: "2026-06-01", endDate: "2026-06-30" };
|
|
258
|
+
const cursor = encodeSalesReportCursor({
|
|
259
|
+
...scope,
|
|
260
|
+
lastSaleTimestamp: "2026-06-20T10:00:00-03:00",
|
|
261
|
+
lastOperationKey: "200001"
|
|
262
|
+
});
|
|
263
|
+
const [payload, signature] = cursor.split(".");
|
|
264
|
+
const tampered = `${payload.slice(0, -1)}${payload.endsWith("A") ? "B" : "A"}.${signature}`;
|
|
265
|
+
expect(() => decodeSalesReportCursor(tampered, scope)).toThrow("Invalid sales report cursor");
|
|
266
|
+
});
|
|
267
|
+
it("keeps cursor continuation ordered by instants across offsets", () => {
|
|
268
|
+
const candidate = operation("300", "201", "2026-06-02T00:30:00-03:00");
|
|
269
|
+
expect(isSalesReportOperationAfterCursor(candidate, {
|
|
270
|
+
lastSaleTimestamp: "2026-06-02T00:00:00-04:00",
|
|
271
|
+
lastOperationKey: "200"
|
|
272
|
+
})).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
it("preserves null values while metadata marks unavailable fields", () => {
|
|
275
|
+
const item = operation(null, "200", "2026-06-30T20:00:00-03:00");
|
|
276
|
+
const metadata = buildSalesReportMetadata({
|
|
277
|
+
profileId: "triplim",
|
|
278
|
+
startDate: "2026-06-01",
|
|
279
|
+
endDate: "2026-06-30",
|
|
280
|
+
currencies: ["ARS"],
|
|
281
|
+
itemsReturned: 1,
|
|
282
|
+
requestedLimit: 200,
|
|
283
|
+
packsReturned: 0,
|
|
284
|
+
ordersReturned: 1,
|
|
285
|
+
partialSections: ["facturacion_al_comprador"],
|
|
286
|
+
sourceCoverage: [
|
|
287
|
+
{ fuente: "orders", estado: "complete", solicitados: 1, obtenidos: 1, incidentes: 0 },
|
|
288
|
+
{ fuente: "billing", estado: "unavailable", solicitados: 1, obtenidos: 0, incidentes: 1 }
|
|
289
|
+
],
|
|
290
|
+
fieldProvenance: [
|
|
291
|
+
{
|
|
292
|
+
campo: "facturacion_al_comprador.factura_adjunta",
|
|
293
|
+
fuente: "billing",
|
|
294
|
+
estado: "unavailable",
|
|
295
|
+
detalle: "Billing source was unavailable for this order."
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
scopedIncidents: [
|
|
299
|
+
{
|
|
300
|
+
fuente: "billing",
|
|
301
|
+
alcance: "order",
|
|
302
|
+
identificadores: ["200"],
|
|
303
|
+
mensaje: "Billing request failed.",
|
|
304
|
+
reintentable: true
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
unsupportedFields: ["facturacion_al_comprador.factura_adjunta"],
|
|
308
|
+
hasMore: false
|
|
309
|
+
});
|
|
310
|
+
expect(item.ordenes[0].facturacion_al_comprador.factura_adjunta).toBeNull();
|
|
311
|
+
expect(metadata.cobertura_completa).toBe(false);
|
|
312
|
+
expect(metadata.campos_no_disponibles).toContain(
|
|
313
|
+
"facturacion_al_comprador.factura_adjunta"
|
|
314
|
+
);
|
|
315
|
+
expect(metadata).not.toHaveProperty("procedencia_de_campos");
|
|
316
|
+
expect(metadata.cobertura_por_fuente).toContainEqual(
|
|
317
|
+
expect.objectContaining({ fuente: "billing", estado: "unavailable" })
|
|
318
|
+
);
|
|
319
|
+
expect(metadata.incidentes_acotados).toContainEqual(
|
|
320
|
+
expect.objectContaining({ fuente: "billing", identificadores: ["200"] })
|
|
321
|
+
);
|
|
322
|
+
expect(metadata.cursor_siguiente).toBeNull();
|
|
323
|
+
expect(metadata.guia_de_continuacion).toBeNull();
|
|
324
|
+
expect(metadata.motivo_del_corte).toBeNull();
|
|
325
|
+
});
|
|
326
|
+
it("provides explicit guidance when more operations remain", () => {
|
|
327
|
+
const metadata = buildSalesReportMetadata({
|
|
328
|
+
profileId: "triplim",
|
|
329
|
+
startDate: "2026-06-01",
|
|
330
|
+
endDate: "2026-06-30",
|
|
331
|
+
itemsReturned: 1,
|
|
332
|
+
requestedLimit: 1,
|
|
333
|
+
packsReturned: 0,
|
|
334
|
+
ordersReturned: 1,
|
|
335
|
+
hasMore: true,
|
|
336
|
+
nextCursor: "opaque-cursor"
|
|
337
|
+
});
|
|
338
|
+
expect(metadata.guia_de_continuacion).toContain("cursor_siguiente");
|
|
339
|
+
expect(metadata.guia_de_continuacion).not.toContain("opaque-cursor");
|
|
340
|
+
});
|
|
341
|
+
it("marks explicit selection metadata as non-paginated and date-independent", () => {
|
|
342
|
+
const metadata = buildSalesReportMetadata({
|
|
343
|
+
profileId: "triplim",
|
|
344
|
+
startDate: null,
|
|
345
|
+
endDate: null,
|
|
346
|
+
selectionMode: "ordenes_explicitas",
|
|
347
|
+
explicitSelection: {
|
|
348
|
+
ids_solicitados: ["b", "a", "b", "missing"],
|
|
349
|
+
ids_unicos: ["b", "a", "missing"],
|
|
350
|
+
cantidad_solicitada: 4,
|
|
351
|
+
cantidad_unica: 3,
|
|
352
|
+
cantidad_duplicada: 1,
|
|
353
|
+
ids_resueltos: ["b", "a"],
|
|
354
|
+
cantidad_resuelta: 2,
|
|
355
|
+
ids_no_disponibles: ["missing"],
|
|
356
|
+
cantidad_no_disponible: 1
|
|
357
|
+
},
|
|
358
|
+
itemsReturned: 2,
|
|
359
|
+
requestedLimit: null,
|
|
360
|
+
packsReturned: 0,
|
|
361
|
+
ordersReturned: 2,
|
|
362
|
+
scopedIncidents: [{ fuente: "orders", alcance: "order_selection", identificadores: ["missing"], mensaje: "Unavailable.", reintentable: false }],
|
|
363
|
+
hasMore: false
|
|
364
|
+
});
|
|
365
|
+
expect(metadata).toEqual(expect.objectContaining({
|
|
366
|
+
modo_seleccion: "ordenes_explicitas",
|
|
367
|
+
fecha_desde: null,
|
|
368
|
+
fecha_hasta: null,
|
|
369
|
+
limite_solicitado: null,
|
|
370
|
+
tiene_mas: false,
|
|
371
|
+
cursor_siguiente: null,
|
|
372
|
+
guia_de_continuacion: null,
|
|
373
|
+
cobertura_completa: false
|
|
374
|
+
}));
|
|
375
|
+
expect(metadata.seleccion_explicita).toEqual(expect.objectContaining({ cantidad_duplicada: 1, ids_resueltos: ["b", "a"] }));
|
|
376
|
+
expect(metadata).not.toHaveProperty("procedencia_de_campos");
|
|
377
|
+
});
|
|
378
|
+
it("derives unavailable field metadata from provenance", () => {
|
|
379
|
+
const metadata = buildSalesReportMetadata({
|
|
380
|
+
profileId: "triplim",
|
|
381
|
+
startDate: "2026-06-01",
|
|
382
|
+
endDate: "2026-06-30",
|
|
383
|
+
itemsReturned: 1,
|
|
384
|
+
requestedLimit: 200,
|
|
385
|
+
packsReturned: 0,
|
|
386
|
+
ordersReturned: 1,
|
|
387
|
+
fieldProvenance: [
|
|
388
|
+
{
|
|
389
|
+
campo: "ventas.total_ars",
|
|
390
|
+
fuente: "billing",
|
|
391
|
+
estado: "unavailable",
|
|
392
|
+
detalle: "Billing was unavailable."
|
|
393
|
+
}
|
|
394
|
+
],
|
|
395
|
+
hasMore: false
|
|
396
|
+
});
|
|
397
|
+
expect(metadata.cobertura_completa).toBe(false);
|
|
398
|
+
expect(metadata.campos_no_disponibles).toEqual(["ventas.total_ars"]);
|
|
399
|
+
expect(metadata).not.toHaveProperty("procedencia_de_campos");
|
|
400
|
+
});
|
|
401
|
+
it("plans bounded remaining pages from effective seed paging", () => {
|
|
402
|
+
expect(buildOrderUniversePagePlan({ total: 121, limit: 50, offset: 0 }, 100)).toEqual([50, 100]);
|
|
403
|
+
expect(buildOrderUniversePagePlan({ total: 201, limit: 50, offset: 0 }, 200)).toEqual([50, 100, 150, 200]);
|
|
404
|
+
expect(buildOrderUniversePagePlan({ total: 1e3, limit: 50, offset: 0 }, 150, 2)).toEqual([50, 100]);
|
|
405
|
+
});
|
|
406
|
+
it("groups packs without splitting them and preserves explicit nulls", () => {
|
|
407
|
+
const first = { id: 1, pack_id: 9, date_created: "2026-06-30T10:00:00-03:00", total_amount: null };
|
|
408
|
+
const second = { id: 2, pack_id: 9, date_created: "2026-06-30T11:00:00-03:00" };
|
|
409
|
+
const standalone = { id: 3, date_created: "2026-06-29T11:00:00-03:00" };
|
|
410
|
+
expect(groupMercadoLibreOrders([first, second, standalone]).map((item) => [item.pack_id, item.ordenes.map((order2) => order2.order_id)])).toEqual([
|
|
411
|
+
["9", ["1", "2"]],
|
|
412
|
+
[null, ["3"]]
|
|
413
|
+
]);
|
|
414
|
+
expect(groupMercadoLibreOrders([first])[0].ordenes[0].ventas.ingresos_por_productos_ars).toBeNull();
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
//# sourceMappingURL=get-sales-report-foundation.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/mercadolibre/__tests__/get-sales-report-foundation.test.ts"],
|
|
4
|
+
"sourcesContent": ["import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport {\n buildSalesReportDateBoundaries,\n buildSalesReportMetadata,\n createSalesReportPerformanceTracker,\n decodeSalesReportCursor,\n encodeSalesReportCursor,\n getSalesReportOperationSaleTimestamp,\n isSalesReportOperationAfterCursor,\n meliGetSalesReportSchema,\n sortSalesReportOperations,\n type SalesReportOperation,\n type SalesReportOrder,\n} from \"../get-sales-report.js\";\nimport {\n buildOrderUniversePagePlan,\n groupMercadoLibreOrders,\n} from \"../../../services/mercadolibre/mercadolibre-sales-report.js\";\n\nconst TEST_KEY = \"11\".repeat(32);\n\nfunction order(orderId: string, saleDate: string): SalesReportOrder {\n return {\n order_id: orderId,\n ventas: {\n fecha_de_venta: saleDate,\n estado: null,\n descripcion_del_estado: null,\n pertenece_a_un_kit: null,\n unidades: null,\n ingresos_por_productos_ars: null,\n orden_de_compra: null,\n },\n publicidad: { venta_por_publicidad: null },\n publicaciones: {\n sku: null,\n numero_de_publicacion: null,\n canal_de_venta: null,\n titulo_de_la_publicacion: null,\n variante: null,\n precio_unitario_de_venta_de_la_publicacion_ars: null,\n tiene_cuotas_agregadas: null,\n },\n facturacion_al_comprador: {\n factura_adjunta: null,\n datos_personales_o_de_empresa: null,\n tipo_y_numero_de_documento: null,\n direccion: null,\n condicion_fiscal_iva: null,\n numero_iibb: null,\n },\n compradores: {\n comprador: null,\n negocio: null,\n dni: null,\n domicilio: null,\n ciudad: null,\n estado: null,\n codigo_postal: null,\n pais: null,\n },\n envios: {\n forma_de_entrega: null,\n fecha_en_camino: null,\n fecha_entregado: null,\n transportista: null,\n numero_de_seguimiento: null,\n url_de_seguimiento: null,\n },\n devoluciones: {\n unidades: null,\n forma_de_entrega: null,\n fecha_en_camino: null,\n fecha_entregado: null,\n transportista: null,\n numero_de_seguimiento: null,\n url_de_seguimiento: null,\n revisado_por_mercado_libre: null,\n fecha_de_revision: null,\n dinero_a_favor: null,\n resultado: null,\n destino: null,\n motivo_del_resultado: null,\n },\n reclamos: {\n unidades: null,\n reclamo_abierto: null,\n reclamo_cerrado: null,\n con_mediacion: null,\n },\n };\n}\n\nfunction operation(packId: string | null, orderId: string, saleDate: string): SalesReportOperation {\n return {\n pack_id: packId,\n ventas: {\n paquete_de_varios_productos: packId !== null,\n cargo_por_venta: null,\n costo_fijo: null,\n costo_por_ofrecer_cuotas: null,\n ingresos_por_envio_ars: null,\n costos_de_envio_ars: null,\n costo_de_envio_por_cambio_de_producto: null,\n costo_de_envio_basado_en_medidas_y_peso_declarados: null,\n cargo_por_diferencias_en_medidas_y_peso_del_paquete: null,\n impuestos: null,\n descuentos_y_bonificaciones: null,\n anulaciones_y_reembolsos_ars: null,\n total_ars: null,\n periodos_de_facturacion: [],\n },\n ordenes: [order(orderId, saleDate)],\n };\n}\n\ndescribe(\"meli_get_sales_report Phase 0 foundation\", () => {\n const originalKey = process.env.DB_ENCRYPTION_KEY;\n\n beforeEach(() => {\n process.env.DB_ENCRYPTION_KEY = TEST_KEY;\n });\n\n afterEach(() => {\n if (originalKey === undefined) delete process.env.DB_ENCRYPTION_KEY;\n else process.env.DB_ENCRYPTION_KEY = originalKey;\n });\n\n it(\"tracks monotonic stage and total durations deterministically\", async () => {\n let currentTime = 100;\n const tracker = createSalesReportPerformanceTracker(() => currentTime);\n const stageStartedAt = tracker.start();\n currentTime = 104.6;\n expect(tracker.finish(\"seleccion\", stageStartedAt)).toBe(5);\n\n await tracker.measure(\"postventa\", async () => {\n currentTime = 111.2;\n });\n currentTime = 115;\n\n expect(tracker.duration(\"seleccion\")).toBe(5);\n expect(tracker.duration(\"postventa\")).toBe(7);\n expect(tracker.duration(\"ausente\")).toBe(0);\n expect(tracker.total()).toBe(15);\n });\n\n it(\"validates input and applies the default and maximum limits\", () => {\n expect(\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n }).limit ?? 200\n ).toBe(200);\n expect(\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n limit: 1000,\n }).limit\n ).toBe(1000);\n expect(() =>\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-02-30\",\n endDate: \"2026-06-30\",\n })\n ).toThrow();\n expect(() =>\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n billingPeriod: \"2026-06\",\n })\n ).toThrow();\n expect(() =>\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n limit: 1001,\n })\n ).toThrow();\n });\n\n it(\"accepts strict range and explicit-order modes with trimmed stable duplicates\", () => {\n expect(meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n })).toEqual(expect.objectContaining({ startDate: \"2026-06-01\", endDate: \"2026-06-30\" }));\n expect(meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n orderIds: [\" order-b \", \"order-a\", \"order-b\"],\n }).orderIds).toEqual([\"order-b\", \"order-a\", \"order-b\"]);\n });\n\n it.each([\n { profileId: \"triplim\", orderIds: [], label: \"empty list\" },\n { profileId: \"triplim\", orderIds: Array.from({ length: 101 }, (_, index) => `order-${index}`), label: \"more than 100 IDs\" },\n { profileId: \"triplim\", orderIds: [\" \"], label: \"empty item\" },\n { profileId: \"triplim\", orderIds: [\"order-1\"], startDate: \"2026-06-01\", endDate: \"2026-06-30\", label: \"dates in explicit mode\" },\n { profileId: \"triplim\", orderIds: [\"order-1\"], limit: 1, label: \"limit in explicit mode\" },\n { profileId: \"triplim\", orderIds: [\"order-1\"], cursor: \"cursor\", label: \"cursor in explicit mode\" },\n { profileId: \"triplim\", startDate: \"2026-06-01\", label: \"incomplete range\" },\n ])(\"rejects $label\", ({ label: _label, ...input }) => {\n expect(() => meliGetSalesReportSchema.parse(input)).toThrow();\n });\n\n it(\"rejects reversed sales dates\", () => {\n expect(() =>\n meliGetSalesReportSchema.parse({\n profileId: \"triplim\",\n startDate: \"2026-07-01\",\n endDate: \"2026-06-30\",\n })\n ).toThrow(\"endDate must be on or after startDate\");\n });\n\n it(\"builds inclusive Buenos Aires timezone boundaries\", () => {\n expect(buildSalesReportDateBoundaries(\"2026-06-01\", \"2026-06-30\")).toEqual({\n timeZone: \"America/Argentina/Buenos_Aires\",\n from: \"2026-06-01T00:00:00.000-03:00\",\n to: \"2026-06-30T23:59:59.999-03:00\",\n });\n });\n\n it(\"uses the historical Buenos Aires offset for date boundaries\", () => {\n expect(buildSalesReportDateBoundaries(\"2008-01-01\", \"2008-01-31\")).toEqual({\n timeZone: \"America/Argentina/Buenos_Aires\",\n from: \"2008-01-01T00:00:00.000-02:00\",\n to: \"2008-01-31T23:59:59.999-02:00\",\n });\n });\n\n it(\"orders operations by sale date and then operation key descending without mutation\", () => {\n const original = [\n operation(null, \"200\", \"2026-06-30T20:00:00-03:00\"),\n operation(\"300\", \"201\", \"2026-06-30T20:00:00-03:00\"),\n operation(null, \"999\", \"2026-06-29T20:00:00-03:00\"),\n ];\n\n const sorted = sortSalesReportOperations(original);\n expect(sorted.map((item) => item.pack_id ?? item.ordenes[0].order_id)).toEqual([\n \"300\",\n \"200\",\n \"999\",\n ]);\n expect(original[0].ordenes[0].order_id).toBe(\"200\");\n });\n\n it(\"chooses the latest sale by instant when timestamps have mixed offsets\", () => {\n const packed = operation(\"300\", \"201\", \"2026-06-02T00:30:00-03:00\");\n packed.ordenes.push(order(\"202\", \"2026-06-02T00:00:00-04:00\"));\n\n expect(getSalesReportOperationSaleTimestamp(packed)).toBe(\"2026-06-02T00:00:00-04:00\");\n });\n\n it(\"round-trips a self-contained cursor and rejects scope changes\", () => {\n const scope = { profileId: \"triplim\", startDate: \"2026-06-01\", endDate: \"2026-06-30\" };\n const cursor = encodeSalesReportCursor({\n ...scope,\n lastSaleTimestamp: \"2026-06-20T10:00:00-03:00\",\n lastOperationKey: \"200001\",\n });\n\n expect(decodeSalesReportCursor(cursor, scope)).toEqual({\n version: 1,\n ...scope,\n lastSaleTimestamp: \"2026-06-20T10:00:00-03:00\",\n lastOperationKey: \"200001\",\n });\n expect(() =>\n decodeSalesReportCursor(cursor, { ...scope, profileId: \"another-profile\" })\n ).toThrow(\"does not match the requested report scope\");\n });\n\n it(\"rejects cursor tampering\", () => {\n const scope = { profileId: \"triplim\", startDate: \"2026-06-01\", endDate: \"2026-06-30\" };\n const cursor = encodeSalesReportCursor({\n ...scope,\n lastSaleTimestamp: \"2026-06-20T10:00:00-03:00\",\n lastOperationKey: \"200001\",\n });\n const [payload, signature] = cursor.split(\".\");\n const tampered = `${payload.slice(0, -1)}${payload.endsWith(\"A\") ? \"B\" : \"A\"}.${signature}`;\n\n expect(() => decodeSalesReportCursor(tampered, scope)).toThrow(\"Invalid sales report cursor\");\n });\n\n it(\"keeps cursor continuation ordered by instants across offsets\", () => {\n const candidate = operation(\"300\", \"201\", \"2026-06-02T00:30:00-03:00\");\n expect(isSalesReportOperationAfterCursor(candidate, {\n lastSaleTimestamp: \"2026-06-02T00:00:00-04:00\",\n lastOperationKey: \"200\",\n })).toBe(true);\n });\n\n it(\"preserves null values while metadata marks unavailable fields\", () => {\n const item = operation(null, \"200\", \"2026-06-30T20:00:00-03:00\");\n const metadata = buildSalesReportMetadata({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n currencies: [\"ARS\"],\n itemsReturned: 1,\n requestedLimit: 200,\n packsReturned: 0,\n ordersReturned: 1,\n partialSections: [\"facturacion_al_comprador\"],\n sourceCoverage: [\n { fuente: \"orders\", estado: \"complete\", solicitados: 1, obtenidos: 1, incidentes: 0 },\n { fuente: \"billing\", estado: \"unavailable\", solicitados: 1, obtenidos: 0, incidentes: 1 },\n ],\n fieldProvenance: [\n {\n campo: \"facturacion_al_comprador.factura_adjunta\",\n fuente: \"billing\",\n estado: \"unavailable\",\n detalle: \"Billing source was unavailable for this order.\",\n },\n ],\n scopedIncidents: [\n {\n fuente: \"billing\",\n alcance: \"order\",\n identificadores: [\"200\"],\n mensaje: \"Billing request failed.\",\n reintentable: true,\n },\n ],\n unsupportedFields: [\"facturacion_al_comprador.factura_adjunta\"],\n hasMore: false,\n });\n\n expect(item.ordenes[0].facturacion_al_comprador.factura_adjunta).toBeNull();\n expect(metadata.cobertura_completa).toBe(false);\n expect(metadata.campos_no_disponibles).toContain(\n \"facturacion_al_comprador.factura_adjunta\"\n );\n expect(metadata).not.toHaveProperty(\"procedencia_de_campos\");\n expect(metadata.cobertura_por_fuente).toContainEqual(\n expect.objectContaining({ fuente: \"billing\", estado: \"unavailable\" })\n );\n expect(metadata.incidentes_acotados).toContainEqual(\n expect.objectContaining({ fuente: \"billing\", identificadores: [\"200\"] })\n );\n expect(metadata.cursor_siguiente).toBeNull();\n expect(metadata.guia_de_continuacion).toBeNull();\n expect(metadata.motivo_del_corte).toBeNull();\n });\n\n it(\"provides explicit guidance when more operations remain\", () => {\n const metadata = buildSalesReportMetadata({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n itemsReturned: 1,\n requestedLimit: 1,\n packsReturned: 0,\n ordersReturned: 1,\n hasMore: true,\n nextCursor: \"opaque-cursor\",\n });\n\n expect(metadata.guia_de_continuacion).toContain(\"cursor_siguiente\");\n expect(metadata.guia_de_continuacion).not.toContain(\"opaque-cursor\");\n });\n\n it(\"marks explicit selection metadata as non-paginated and date-independent\", () => {\n const metadata = buildSalesReportMetadata({\n profileId: \"triplim\",\n startDate: null,\n endDate: null,\n selectionMode: \"ordenes_explicitas\",\n explicitSelection: {\n ids_solicitados: [\"b\", \"a\", \"b\", \"missing\"],\n ids_unicos: [\"b\", \"a\", \"missing\"],\n cantidad_solicitada: 4,\n cantidad_unica: 3,\n cantidad_duplicada: 1,\n ids_resueltos: [\"b\", \"a\"],\n cantidad_resuelta: 2,\n ids_no_disponibles: [\"missing\"],\n cantidad_no_disponible: 1,\n },\n itemsReturned: 2,\n requestedLimit: null,\n packsReturned: 0,\n ordersReturned: 2,\n scopedIncidents: [{ fuente: \"orders\", alcance: \"order_selection\", identificadores: [\"missing\"], mensaje: \"Unavailable.\", reintentable: false }],\n hasMore: false,\n });\n expect(metadata).toEqual(expect.objectContaining({\n modo_seleccion: \"ordenes_explicitas\",\n fecha_desde: null,\n fecha_hasta: null,\n limite_solicitado: null,\n tiene_mas: false,\n cursor_siguiente: null,\n guia_de_continuacion: null,\n cobertura_completa: false,\n }));\n expect(metadata.seleccion_explicita).toEqual(expect.objectContaining({ cantidad_duplicada: 1, ids_resueltos: [\"b\", \"a\"] }));\n expect(metadata).not.toHaveProperty(\"procedencia_de_campos\");\n });\n\n it(\"derives unavailable field metadata from provenance\", () => {\n const metadata = buildSalesReportMetadata({\n profileId: \"triplim\",\n startDate: \"2026-06-01\",\n endDate: \"2026-06-30\",\n itemsReturned: 1,\n requestedLimit: 200,\n packsReturned: 0,\n ordersReturned: 1,\n fieldProvenance: [\n {\n campo: \"ventas.total_ars\",\n fuente: \"billing\",\n estado: \"unavailable\",\n detalle: \"Billing was unavailable.\",\n },\n ],\n hasMore: false,\n });\n\n expect(metadata.cobertura_completa).toBe(false);\n expect(metadata.campos_no_disponibles).toEqual([\"ventas.total_ars\"]);\n expect(metadata).not.toHaveProperty(\"procedencia_de_campos\");\n });\n\n it(\"plans bounded remaining pages from effective seed paging\", () => {\n expect(buildOrderUniversePagePlan({ total: 121, limit: 50, offset: 0 }, 100)).toEqual([50, 100]);\n expect(buildOrderUniversePagePlan({ total: 201, limit: 50, offset: 0 }, 200)).toEqual([50, 100, 150, 200]);\n expect(buildOrderUniversePagePlan({ total: 1000, limit: 50, offset: 0 }, 150, 2)).toEqual([50, 100]);\n });\n\n it(\"groups packs without splitting them and preserves explicit nulls\", () => {\n const first = { id: 1, pack_id: 9, date_created: \"2026-06-30T10:00:00-03:00\", total_amount: null };\n const second = { id: 2, pack_id: 9, date_created: \"2026-06-30T11:00:00-03:00\" };\n const standalone = { id: 3, date_created: \"2026-06-29T11:00:00-03:00\" };\n\n expect(groupMercadoLibreOrders([first, second, standalone]).map((item) => [item.pack_id, item.ordenes.map((order) => order.order_id)])).toEqual([\n [\"9\", [\"1\", \"2\"]],\n [null, [\"3\"]],\n ]);\n expect(groupMercadoLibreOrders([first])[0].ordenes[0].ventas.ingresos_por_productos_ars).toBeNull();\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["order"]
|
|
7
|
+
}
|