@yoryoboy/bi-mcp 1.7.0 → 1.9.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.
Files changed (31) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/index.js +27 -5
  3. package/dist/index.js.map +2 -2
  4. package/dist/mcp-use.json +6 -3
  5. package/dist/src/services/mercadolibre/mercadolibre-billing.js +77 -0
  6. package/dist/src/services/mercadolibre/mercadolibre-billing.js.map +7 -0
  7. package/dist/src/services/mercadolibre/mercadolibre-items.js +29 -2
  8. package/dist/src/services/mercadolibre/mercadolibre-items.js.map +2 -2
  9. package/dist/src/services/mercadolibre/mercadolibre-orders.js +18 -0
  10. package/dist/src/services/mercadolibre/mercadolibre-orders.js.map +2 -2
  11. package/dist/src/tools/mercadolibre/estimate-listing-fee.js +26 -34
  12. package/dist/src/tools/mercadolibre/estimate-listing-fee.js.map +2 -2
  13. package/dist/src/tools/mercadolibre/estimate-product-profitability.js +546 -0
  14. package/dist/src/tools/mercadolibre/estimate-product-profitability.js.map +7 -0
  15. package/dist/src/tools/mercadolibre/get-item-details.js +3 -25
  16. package/dist/src/tools/mercadolibre/get-item-details.js.map +2 -2
  17. package/dist/src/tools/mercadolibre/get-sales-by-item.js +129 -14
  18. package/dist/src/tools/mercadolibre/get-sales-by-item.js.map +2 -2
  19. package/dist/src/tools/mercadolibre/get-sales-trend.js +137 -14
  20. package/dist/src/tools/mercadolibre/get-sales-trend.js.map +2 -2
  21. package/dist/src/tools/mercadolibre/get-shipping-summary.js +450 -57
  22. package/dist/src/tools/mercadolibre/get-shipping-summary.js.map +2 -2
  23. package/dist/src/tools/mercadolibre/get-site-categories-and-listing-types.js +50 -0
  24. package/dist/src/tools/mercadolibre/get-site-categories-and-listing-types.js.map +7 -0
  25. package/dist/src/tools/mercadolibre/index.js +2 -0
  26. package/dist/src/tools/mercadolibre/index.js.map +2 -2
  27. package/dist/src/tools/mercadolibre/listing-fee-helpers.js +265 -0
  28. package/dist/src/tools/mercadolibre/listing-fee-helpers.js.map +7 -0
  29. package/dist/src/tools/mercadolibre/search-items.js +207 -52
  30. package/dist/src/tools/mercadolibre/search-items.js.map +2 -2
  31. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/tools/mercadolibre/get-shipping-summary.ts"],
4
- "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatMercadoLibreError } from \"../../services/mercadolibre/mercadolibre-api.js\";\nimport {\n getMercadoLibreShipment,\n getMercadoLibreShipmentCosts,\n searchMercadoLibreOrders,\n} from \"../../services/mercadolibre/mercadolibre-orders.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport {\n asArray,\n asRecord,\n currencyBucket,\n mercadoLibreDateRegex,\n normalizeString,\n roundMoney,\n toNumber,\n} from \"./helpers.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"./profile-resolution.js\";\nimport { mercadolibreProfileIdSchemaField } from \"./write-helpers.js\";\n\nexport const meliGetShippingSummarySchema = z.object({\n profileId: mercadolibreProfileIdSchemaField,\n startDate: z.string().regex(mercadoLibreDateRegex).describe(\"Start date in YYYY-MM-DD format.\"),\n endDate: z.string().regex(mercadoLibreDateRegex).describe(\"End date in YYYY-MM-DD format.\"),\n status: z.string().trim().min(1).optional().describe(\"Optional order status filter.\"),\n limit: z.number().int().min(1).max(30).optional().describe(\"Orders page size to inspect for shipping data.\"),\n offset: z.number().int().min(0).max(5000).optional().describe(\"Orders offset to inspect.\"),\n});\n\nexport async function meliGetShippingSummaryHandler(\n params: z.infer<typeof meliGetShippingSummarySchema>\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 const ordersResponse = await searchMercadoLibreOrders(profileId, {\n seller: \"\",\n from: params.startDate,\n to: params.endDate,\n status: params.status,\n limit: params.limit ?? 20,\n offset: params.offset ?? 0,\n });\n\n const statusCounts: Record<string, number> = {};\n const substatusCounts: Record<string, number> = {};\n const costsByCurrency: Record<string, { shipments: number; total_cost: number }> = {};\n const partialFailures: Array<{ order_id?: string; shipment_id?: string; message: string }> = [];\n const shipmentRows: Array<Record<string, unknown>> = [];\n\n for (const order of asArray<Record<string, unknown>>(ordersResponse.results)) {\n const shipping = asRecord(order.shipping);\n const shipmentId = normalizeString(shipping.id);\n if (!shipmentId) {\n continue;\n }\n\n try {\n const [shipment, costs] = await Promise.all([\n getMercadoLibreShipment(profileId, shipmentId),\n getMercadoLibreShipmentCosts(profileId, shipmentId),\n ]);\n const shipmentStatus = normalizeString(shipment.status, \"unknown\");\n const shipmentSubstatus = normalizeString(shipment.substatus, \"unknown\");\n statusCounts[shipmentStatus] = (statusCounts[shipmentStatus] ?? 0) + 1;\n substatusCounts[shipmentSubstatus] = (substatusCounts[shipmentSubstatus] ?? 0) + 1;\n\n const currencyId = normalizeString(order.currency_id, \"UNKNOWN\");\n const bucket = currencyBucket(costsByCurrency, currencyId, () => ({ shipments: 0, total_cost: 0 }));\n bucket.shipments += 1;\n bucket.total_cost +=\n toNumber(asRecord(costs.senders).cost) ||\n toNumber(asRecord(costs.receiver).cost) ||\n toNumber(costs.gross_amount) ||\n toNumber(costs.cost);\n\n shipmentRows.push(\n stripNulls({\n order_id: normalizeString(order.id),\n shipment_id: shipmentId,\n status: shipmentStatus,\n substatus: shipmentSubstatus,\n logistic_type: normalizeString(shipment.logistic_type),\n mode: normalizeString(shipment.mode),\n currency_id: currencyId,\n cost: roundMoney(bucket.total_cost),\n })\n );\n } catch (shipmentError) {\n partialFailures.push({\n order_id: normalizeString(order.id),\n shipment_id: shipmentId,\n message: formatMercadoLibreError(shipmentError, `Failed to inspect shipment ${shipmentId}`),\n });\n }\n }\n\n for (const metrics of Object.values(costsByCurrency)) {\n metrics.total_cost = roundMoney(metrics.total_cost);\n }\n\n return object(\n stripNulls({\n profile_id: profileId,\n metadata: {\n orders_inspected: asArray(ordersResponse.results).length,\n shipments_inspected: shipmentRows.length,\n partial_failures: partialFailures.length,\n has_partial_failures: partialFailures.length > 0,\n },\n status_counts: statusCounts,\n substatus_counts: substatusCounts,\n costs_by_currency: costsByCurrency,\n shipments: shipmentRows,\n failures: partialFailures,\n })\n );\n } catch (err) {\n return error(formatMercadoLibreError(err, \"Failed to summarize MercadoLibre shipping\"));\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,6CAA6C;AACtD,SAAS,wCAAwC;AAE1C,MAAM,+BAA+B,EAAE,OAAO;AAAA,EACnD,WAAW;AAAA,EACX,WAAW,EAAE,OAAO,EAAE,MAAM,qBAAqB,EAAE,SAAS,kCAAkC;AAAA,EAC9F,SAAS,EAAE,OAAO,EAAE,MAAM,qBAAqB,EAAE,SAAS,gCAAgC;AAAA,EAC1F,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,EACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,EAC3G,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,2BAA2B;AAC3F,CAAC;AAED,eAAsB,8BACpB,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;AAC1C,UAAM,iBAAiB,MAAM,yBAAyB,WAAW;AAAA,MAC/D,QAAQ;AAAA,MACR,MAAM,OAAO;AAAA,MACb,IAAI,OAAO;AAAA,MACX,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,IAC3B,CAAC;AAED,UAAM,eAAuC,CAAC;AAC9C,UAAM,kBAA0C,CAAC;AACjD,UAAM,kBAA6E,CAAC;AACpF,UAAM,kBAAuF,CAAC;AAC9F,UAAM,eAA+C,CAAC;AAEtD,eAAW,SAAS,QAAiC,eAAe,OAAO,GAAG;AAC5E,YAAM,WAAW,SAAS,MAAM,QAAQ;AACxC,YAAM,aAAa,gBAAgB,SAAS,EAAE;AAC9C,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAEA,UAAI;AACF,cAAM,CAAC,UAAU,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC1C,wBAAwB,WAAW,UAAU;AAAA,UAC7C,6BAA6B,WAAW,UAAU;AAAA,QACpD,CAAC;AACD,cAAM,iBAAiB,gBAAgB,SAAS,QAAQ,SAAS;AACjE,cAAM,oBAAoB,gBAAgB,SAAS,WAAW,SAAS;AACvE,qBAAa,cAAc,KAAK,aAAa,cAAc,KAAK,KAAK;AACrE,wBAAgB,iBAAiB,KAAK,gBAAgB,iBAAiB,KAAK,KAAK;AAEjF,cAAM,aAAa,gBAAgB,MAAM,aAAa,SAAS;AAC/D,cAAM,SAAS,eAAe,iBAAiB,YAAY,OAAO,EAAE,WAAW,GAAG,YAAY,EAAE,EAAE;AAClG,eAAO,aAAa;AACpB,eAAO,cACL,SAAS,SAAS,MAAM,OAAO,EAAE,IAAI,KACrC,SAAS,SAAS,MAAM,QAAQ,EAAE,IAAI,KACtC,SAAS,MAAM,YAAY,KAC3B,SAAS,MAAM,IAAI;AAErB,qBAAa;AAAA,UACX,WAAW;AAAA,YACT,UAAU,gBAAgB,MAAM,EAAE;AAAA,YAClC,aAAa;AAAA,YACb,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,eAAe,gBAAgB,SAAS,aAAa;AAAA,YACrD,MAAM,gBAAgB,SAAS,IAAI;AAAA,YACnC,aAAa;AAAA,YACb,MAAM,WAAW,OAAO,UAAU;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,MACF,SAAS,eAAe;AACtB,wBAAgB,KAAK;AAAA,UACnB,UAAU,gBAAgB,MAAM,EAAE;AAAA,UAClC,aAAa;AAAA,UACb,SAAS,wBAAwB,eAAe,8BAA8B,UAAU,EAAE;AAAA,QAC5F,CAAC;AAAA,MACH;AAAA,IACF;AAEA,eAAW,WAAW,OAAO,OAAO,eAAe,GAAG;AACpD,cAAQ,aAAa,WAAW,QAAQ,UAAU;AAAA,IACpD;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,UAAU;AAAA,UACR,kBAAkB,QAAQ,eAAe,OAAO,EAAE;AAAA,UAClD,qBAAqB,aAAa;AAAA,UAClC,kBAAkB,gBAAgB;AAAA,UAClC,sBAAsB,gBAAgB,SAAS;AAAA,QACjD;AAAA,QACA,eAAe;AAAA,QACf,kBAAkB;AAAA,QAClB,mBAAmB;AAAA,QACnB,WAAW;AAAA,QACX,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,wBAAwB,KAAK,2CAA2C,CAAC;AAAA,EACxF;AACF;",
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport {\n formatMercadoLibreError,\n normalizeMercadoLibrePaging,\n} from \"../../services/mercadolibre/mercadolibre-api.js\";\nimport {\n getMercadoLibreShipmentBatch,\n getMercadoLibreShipmentCostsBatch,\n searchMercadoLibreOrders,\n searchMercadoLibreOrdersBatch,\n} from \"../../services/mercadolibre/mercadolibre-orders.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport {\n asArray,\n asRecord,\n currencyBucket,\n mercadoLibreDateRegex,\n normalizeScalarString,\n normalizeString,\n roundMoney,\n toNumber,\n} from \"./helpers.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"./profile-resolution.js\";\nimport { mercadolibreProfileIdSchemaField } from \"./write-helpers.js\";\n\nconst PAGE_FETCH_CONCURRENCY = 15;\nconst PAGE_FETCH_MAX_RETRIES = 2;\nconst SHIPPING_DETAIL_MAX_PAGES_PER_CALL = 15;\nconst DEFAULT_CALCULATIONS_PAGE_LIMIT = 50;\nconst DEFAULT_SHIPPING_DETAIL_PAGE_LIMIT = 50;\nconst BUSINESS_TIME_ZONE = \"America/Argentina/Buenos_Aires\";\nconst TOP_LIMIT = 10;\nconst shipmentsSchema = [\n \"order_id\",\n \"shipment_id\",\n \"status\",\n \"substatus\",\n \"logistic_type\",\n \"mode\",\n \"currency_id\",\n \"cost\",\n] as const;\n\ntype FailedPage = {\n offset: number;\n limit: number;\n page_number: number;\n message: string;\n status_code?: number;\n attempts: number;\n retryable: boolean;\n};\n\ntype ShipmentFailure = {\n order_id?: string;\n shipment_id?: string;\n stage: \"shipment\" | \"costs\";\n message: string;\n status_code?: number;\n attempts?: number;\n retryable?: boolean;\n};\n\ntype BreakdownEntry = {\n key: string;\n orders: number;\n rate: number;\n};\n\ntype BreakdownResult = {\n entries: BreakdownEntry[];\n other_orders?: number;\n other_rate?: number;\n};\n\ntype ShippingMode = \"calculations\" | \"shipments_chunk\";\n\ntype ShippingMetadata = ReturnType<typeof buildShippingSummaryMetadata>;\n\ntype ShippingCostBucket = {\n shipments: number;\n shipments_with_cost: number;\n zero_cost_shipments: number;\n total_cost: number;\n};\n\ntype DailyShippingMetric = {\n date: string;\n shipments: number;\n delivered_shipments: number;\n cancelled_shipments: number;\n not_delivered_shipments: number;\n shipping_cost_by_currency: Record<string, number>;\n};\n\nfunction safeRate(numerator: number, denominator: number): number {\n if (!Number.isFinite(denominator) || denominator <= 0) {\n return 0;\n }\n\n return Number((numerator / denominator).toFixed(4));\n}\n\nfunction topBreakdownFromMap(\n counts: Map<string, number>,\n total: number,\n limit = TOP_LIMIT\n): BreakdownResult {\n const sorted = Array.from(counts.entries())\n .filter(([, count]) => count > 0)\n .sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]));\n\n const entries = sorted.slice(0, limit).map(([key, orders]) => ({\n key,\n orders,\n rate: safeRate(orders, total),\n }));\n\n const otherOrders = sorted.slice(limit).reduce((sum, [, count]) => sum + count, 0);\n return stripNulls({\n entries,\n other_orders: otherOrders > 0 ? otherOrders : undefined,\n other_rate: otherOrders > 0 ? safeRate(otherOrders, total) : undefined,\n }) as BreakdownResult;\n}\n\nfunction incrementCount(map: Map<string, number>, key: string) {\n if (!key) {\n return;\n }\n\n map.set(key, (map.get(key) ?? 0) + 1);\n}\n\nfunction topSingleValue(counts: Map<string, number>): string {\n return Array.from(counts.entries())\n .filter(([key]) => key)\n .sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]))[0]?.[0] ?? \"\";\n}\n\nfunction incrementCurrency(map: Record<string, number>, currencyId: string, amount: number) {\n map[currencyId] = roundMoney((map[currencyId] ?? 0) + amount);\n}\n\nfunction sortedCurrencyTotals(input: Record<string, number>) {\n return Object.fromEntries(\n Object.entries(input)\n .filter(([, amount]) => amount !== 0)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([currencyId, amount]) => [currencyId, roundMoney(amount)])\n );\n}\n\nfunction formatDateInTimeZone(dateValue: Date, timeZone: string): string {\n const formatter = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n });\n\n const parts = formatter.formatToParts(dateValue);\n const year = parts.find((part) => part.type === \"year\")?.value;\n const month = parts.find((part) => part.type === \"month\")?.value;\n const day = parts.find((part) => part.type === \"day\")?.value;\n\n if (!year || !month || !day) {\n return \"\";\n }\n\n return `${year}-${month}-${day}`;\n}\n\nfunction getLocalDateBucket(createdAt: string, timeZone: string): string {\n if (!createdAt) {\n return \"\";\n }\n\n const date = new Date(createdAt);\n if (Number.isNaN(date.getTime())) {\n return \"\";\n }\n\n return formatDateInTimeZone(date, timeZone);\n}\n\nfunction buildShippingSummaryMetadata(params: {\n total: number;\n effectiveLimit: number;\n effectiveOffset: number;\n returned: number;\n responseMode: ShippingMode;\n pagesRequested: number;\n pagesSucceeded: number;\n pagesFailed: number;\n failedOffsets: number[];\n shipmentFailures: number;\n}) {\n const requestedWindowEndOffset = params.effectiveOffset + params.effectiveLimit * params.pagesRequested;\n const nextOffset =\n params.responseMode === \"shipments_chunk\"\n ? requestedWindowEndOffset\n : params.effectiveOffset + params.returned;\n const hasMoreOrders = nextOffset < params.total;\n const hasFailures = params.pagesFailed > 0 || params.shipmentFailures > 0;\n const universeFullyFetched =\n params.responseMode === \"calculations\" && !hasFailures && params.returned >= params.total;\n\n let continuation = \"No more pages for this query.\";\n if (params.pagesFailed > 0) {\n const offsets = params.failedOffsets.slice(0, 5).join(\", \");\n const moreOffsets =\n params.failedOffsets.length > 5\n ? ` y ${params.failedOffsets.length - 5} offsets adicionales`\n : \"\";\n continuation =\n params.responseMode === \"shipments_chunk\"\n ? `Se recuperaron paginas parciales. Reintentar primero la misma tool con responseMode=\"shipments_chunk\", offset=${params.failedOffsets[0]} y limit=${params.effectiveLimit}. Offsets fallidos: ${offsets}${moreOffsets}. Luego continuar con offset=${nextOffset} si hace falta.`\n : `Calculos parciales por paginas fallidas. Reintentar la misma tool con responseMode=\"calculations\". Offsets fallidos: ${offsets}${moreOffsets}.`;\n } else if (params.shipmentFailures > 0) {\n continuation =\n params.responseMode === \"shipments_chunk\"\n ? `Se recuperaron shipments parciales. Reintentar la misma tool con responseMode=\"shipments_chunk\", offset=${params.effectiveOffset} y limit=${params.effectiveLimit}${hasMoreOrders ? `. Luego continuar con offset=${nextOffset} si hace falta.` : \".\"}`\n : 'Calculos parciales por fallas al consultar shipments o costos. Reintentar la misma tool con responseMode=\"calculations\".';\n } else if (params.responseMode === \"shipments_chunk\" && hasMoreOrders) {\n continuation = `Para continuar trayendo shipments, volver a invocar meli_get_shipping_summary con los mismos filtros, responseMode=\"shipments_chunk\", offset=${nextOffset} y limit=${params.effectiveLimit}. Repetir hasta has_more=false.`;\n } else if (params.responseMode === \"calculations\") {\n continuation = 'Calculos completos. Si el usuario pide detalle de shipments, invocar la misma tool con responseMode=\"shipments_chunk\", offset=0 y limit=50.';\n }\n\n return stripNulls({\n total: params.total,\n limit: params.effectiveLimit,\n offset: params.effectiveOffset,\n returned: params.returned,\n has_more: params.responseMode === \"shipments_chunk\" ? hasMoreOrders || hasFailures : hasFailures,\n next_offset: params.responseMode === \"shipments_chunk\" && hasMoreOrders ? nextOffset : undefined,\n continuation,\n fetch_mode: params.responseMode === \"shipments_chunk\" ? \"shipments_chunk\" : \"full_calculations\",\n pages_per_call_limit:\n params.responseMode === \"shipments_chunk\" ? SHIPPING_DETAIL_MAX_PAGES_PER_CALL : undefined,\n pages_requested: params.pagesRequested,\n pages_succeeded: params.pagesSucceeded,\n pages_failed: params.pagesFailed,\n shipment_failures: params.shipmentFailures,\n universe_fully_fetched: universeFullyFetched,\n });\n}\n\nfunction extractShipmentCost(costs: Record<string, unknown>) {\n return (\n toNumber(asRecord(costs.senders).cost) ||\n toNumber(asRecord(costs.receiver).cost) ||\n toNumber(costs.gross_amount) ||\n toNumber(costs.cost)\n );\n}\n\nfunction formatCompactShipmentRow(params: {\n orderId: string;\n shipmentId: string;\n status: string;\n substatus: string;\n logisticType: string;\n mode: string;\n currencyId: string;\n cost: number;\n}) {\n return [\n params.orderId,\n params.shipmentId,\n params.status,\n params.substatus,\n params.logisticType,\n params.mode,\n params.currencyId,\n params.cost,\n ];\n}\n\nfunction buildShippingCalculations(params: {\n ordersTotal: number;\n ordersWithShipping: number;\n shipmentsRequested: number;\n shipmentsInspected: number;\n deliveredShipments: number;\n cancelledShipments: number;\n notDeliveredShipments: number;\n statusCounts: Map<string, number>;\n substatusCounts: Map<string, number>;\n logisticTypeCounts: Map<string, number>;\n modeCounts: Map<string, number>;\n costsByCurrency: Record<string, ShippingCostBucket>;\n dailyMetrics: Map<string, DailyShippingMetric>;\n metadata: ShippingMetadata;\n failedPages: FailedPage[];\n shipmentFailures: ShipmentFailure[];\n}) {\n const costsByCurrency = Object.fromEntries(\n Object.entries(params.costsByCurrency)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([currencyId, bucket]) => [\n currencyId,\n {\n total_shipping_cost: roundMoney(bucket.total_cost),\n shipments: bucket.shipments,\n shipments_with_cost: bucket.shipments_with_cost,\n zero_cost_shipments: bucket.zero_cost_shipments,\n avg_cost_per_shipment: roundMoney(bucket.total_cost / Math.max(1, bucket.shipments)),\n avg_cost_per_shipment_with_cost: roundMoney(\n bucket.total_cost / Math.max(1, bucket.shipments_with_cost)\n ),\n shipping_cost_rate_by_shipment: safeRate(bucket.shipments_with_cost, bucket.shipments),\n },\n ])\n );\n\n const dailyTrend = Array.from(params.dailyMetrics.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([, metric]) =>\n stripNulls({\n date: metric.date,\n shipments: metric.shipments,\n delivered_shipments: metric.delivered_shipments,\n cancelled_shipments: metric.cancelled_shipments,\n not_delivered_shipments: metric.not_delivered_shipments,\n shipping_cost_by_currency: sortedCurrencyTotals(metric.shipping_cost_by_currency),\n })\n );\n\n return {\n overview: {\n orders_total: params.ordersTotal,\n orders_with_shipping: params.ordersWithShipping,\n shipments_total: params.shipmentsInspected,\n shipments_requested: params.shipmentsRequested,\n shipping_attachment_rate: safeRate(params.ordersWithShipping, params.ordersTotal),\n delivered_shipments: params.deliveredShipments,\n cancelled_shipments: params.cancelledShipments,\n not_delivered_shipments: params.notDeliveredShipments,\n },\n delivery_health: {\n status_breakdown: topBreakdownFromMap(params.statusCounts, Math.max(1, params.shipmentsInspected)),\n substatus_breakdown: topBreakdownFromMap(params.substatusCounts, Math.max(1, params.shipmentsInspected)),\n delivered_rate: safeRate(params.deliveredShipments, params.shipmentsInspected),\n cancelled_rate: safeRate(params.cancelledShipments, params.shipmentsInspected),\n not_delivered_rate: safeRate(params.notDeliveredShipments, params.shipmentsInspected),\n },\n costs_by_currency: costsByCurrency,\n logistics_mix: {\n logistic_type_breakdown: topBreakdownFromMap(\n params.logisticTypeCounts,\n Math.max(1, params.shipmentsInspected)\n ),\n mode_breakdown: topBreakdownFromMap(params.modeCounts, Math.max(1, params.shipmentsInspected)),\n top_logistic_type_by_shipments: topSingleValue(params.logisticTypeCounts),\n top_mode_by_shipments: topSingleValue(params.modeCounts),\n },\n daily_trend: dailyTrend,\n coverage: {\n fetch_mode: params.metadata.fetch_mode,\n universe_fully_fetched: params.metadata.universe_fully_fetched,\n orders_returned: params.metadata.returned,\n shipments_requested: params.shipmentsRequested,\n shipments_inspected: params.shipmentsInspected,\n pages_requested: params.metadata.pages_requested,\n pages_succeeded: params.metadata.pages_succeeded,\n pages_failed: params.metadata.pages_failed,\n failed_pages_count: params.failedPages.length,\n shipment_failures_count: params.shipmentFailures.length,\n failed_pages: params.failedPages,\n },\n };\n}\n\nexport const meliGetShippingSummarySchema = z.object({\n profileId: mercadolibreProfileIdSchemaField,\n startDate: z.string().regex(mercadoLibreDateRegex).describe(\"Start date in YYYY-MM-DD format.\"),\n endDate: z.string().regex(mercadoLibreDateRegex).describe(\"End date in YYYY-MM-DD format.\"),\n status: z.string().trim().min(1).optional().describe(\"Optional order status filter.\"),\n responseMode: z\n .enum([\"calculations\", \"shipments_chunk\"])\n .optional()\n .default(\"calculations\")\n .describe(\n 'Response mode. calculations (default) fetches all matching orders internally and returns only aggregate shipping KPIs. shipments_chunk returns compact shipment rows for up to 15 MercadoLibre pages and includes continuation metadata.'\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(\n 'MercadoLibre page size for responseMode=\"shipments_chunk\" (1-50). Defaults to 50.'\n ),\n offset: z\n .number()\n .int()\n .min(0)\n .max(5000)\n .optional()\n .describe(\n 'Starting offset for responseMode=\"shipments_chunk\". Use metadata.next_offset to continue.'\n ),\n});\n\nexport async function meliGetShippingSummaryHandler(\n params: z.infer<typeof meliGetShippingSummarySchema>\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 const responseMode = params.responseMode ?? \"calculations\";\n const requestedLimit =\n responseMode === \"shipments_chunk\"\n ? params.limit ?? DEFAULT_SHIPPING_DETAIL_PAGE_LIMIT\n : DEFAULT_CALCULATIONS_PAGE_LIMIT;\n const requestedOffset = responseMode === \"shipments_chunk\" ? params.offset ?? 0 : 0;\n const maxPagesForResponse =\n responseMode === \"shipments_chunk\" ? SHIPPING_DETAIL_MAX_PAGES_PER_CALL : Infinity;\n\n const response = await searchMercadoLibreOrders(profileId, {\n seller: \"\",\n from: params.startDate,\n to: params.endDate,\n status: params.status,\n limit: requestedLimit,\n offset: requestedOffset,\n });\n\n const paging = normalizeMercadoLibrePaging(asRecord(response.paging));\n const baseOrders = asArray<Record<string, unknown>>(response.results);\n const effectiveLimit = paging.limit || requestedLimit || baseOrders.length;\n const effectiveOffset = paging.offset || requestedOffset || 0;\n const allOrders = [...baseOrders];\n const failedPages: FailedPage[] = [];\n let pagesRequested = 1;\n let pagesSucceeded = 1;\n\n if (effectiveLimit > 0 && paging.total > baseOrders.length) {\n const nextOffsets: number[] = [];\n const maxPagesRemaining = Math.max(0, maxPagesForResponse - 1);\n let pagesAdded = 0;\n\n for (let nextOffset = effectiveOffset + effectiveLimit; nextOffset < paging.total; nextOffset += effectiveLimit) {\n if (responseMode === \"shipments_chunk\" && pagesAdded >= maxPagesRemaining) {\n break;\n }\n\n nextOffsets.push(nextOffset);\n pagesAdded += 1;\n }\n\n pagesRequested += nextOffsets.length;\n\n if (nextOffsets.length > 0) {\n const batch = await searchMercadoLibreOrdersBatch(\n profileId,\n {\n seller: \"\",\n from: params.startDate,\n to: params.endDate,\n status: params.status,\n limit: effectiveLimit,\n },\n nextOffsets,\n {\n maxConcurrency: PAGE_FETCH_CONCURRENCY,\n maxRetries: PAGE_FETCH_MAX_RETRIES,\n }\n );\n\n pagesSucceeded += batch.successful.length;\n batch.successful.forEach((entry) => {\n allOrders.push(...asArray<Record<string, unknown>>(entry.document.results));\n });\n batch.failed.forEach((failure) => {\n const failedOffset = Number(failure.id);\n failedPages.push({\n offset: failedOffset,\n limit: effectiveLimit,\n page_number: Math.floor(failedOffset / effectiveLimit) + 1,\n message: failure.message,\n status_code: failure.statusCode,\n attempts: failure.attempts,\n retryable: failure.retryable,\n });\n });\n }\n }\n\n const ordersWithShipping = allOrders.reduce((count, order) => {\n return normalizeScalarString(asRecord(order.shipping).id) ? count + 1 : count;\n }, 0);\n\n const orderByShipmentId = new Map<string, Record<string, unknown>>();\n for (const order of allOrders) {\n const shipmentId = normalizeScalarString(asRecord(order.shipping).id);\n if (shipmentId && !orderByShipmentId.has(shipmentId)) {\n orderByShipmentId.set(shipmentId, order);\n }\n }\n\n const shipmentIds = [...orderByShipmentId.keys()];\n const statusCounts = new Map<string, number>();\n const substatusCounts = new Map<string, number>();\n const logisticTypeCounts = new Map<string, number>();\n const modeCounts = new Map<string, number>();\n const costsByCurrency: Record<string, ShippingCostBucket> = {};\n const dailyMetrics = new Map<string, DailyShippingMetric>();\n const failures: ShipmentFailure[] = [];\n const shipmentRows: Array<(string | number)[]> = [];\n let shipmentsInspected = 0;\n let deliveredShipments = 0;\n let cancelledShipments = 0;\n let notDeliveredShipments = 0;\n\n if (shipmentIds.length > 0) {\n const [shipmentsBatch, costsBatch] = await Promise.all([\n getMercadoLibreShipmentBatch(profileId, shipmentIds, {\n maxConcurrency: PAGE_FETCH_CONCURRENCY,\n maxRetries: PAGE_FETCH_MAX_RETRIES,\n }),\n getMercadoLibreShipmentCostsBatch(profileId, shipmentIds, {\n maxConcurrency: PAGE_FETCH_CONCURRENCY,\n maxRetries: PAGE_FETCH_MAX_RETRIES,\n }),\n ]);\n\n const shipmentById = new Map(\n shipmentsBatch.successful.map((entry) => [entry.id, entry.document] as const)\n );\n const costsByShipmentId = new Map(\n costsBatch.successful.map((entry) => [entry.id, entry.document] as const)\n );\n\n shipmentsBatch.failed.forEach((failure) => {\n failures.push({\n order_id: normalizeScalarString(orderByShipmentId.get(failure.id)?.id),\n shipment_id: failure.id,\n stage: \"shipment\",\n message: failure.message,\n status_code: failure.statusCode,\n attempts: failure.attempts,\n retryable: failure.retryable,\n });\n });\n\n costsBatch.failed.forEach((failure) => {\n failures.push({\n order_id: normalizeScalarString(orderByShipmentId.get(failure.id)?.id),\n shipment_id: failure.id,\n stage: \"costs\",\n message: failure.message,\n status_code: failure.statusCode,\n attempts: failure.attempts,\n retryable: failure.retryable,\n });\n });\n\n for (const shipmentId of shipmentIds) {\n const shipment = shipmentById.get(shipmentId);\n const costs = costsByShipmentId.get(shipmentId);\n if (!shipment || !costs) {\n continue;\n }\n\n const order = orderByShipmentId.get(shipmentId);\n const shipmentStatus = normalizeString(shipment.status, \"unknown\");\n const shipmentSubstatus = normalizeString(shipment.substatus, \"unknown\");\n const logisticType = normalizeString(shipment.logistic_type);\n const mode = normalizeString(shipment.mode);\n const currencyId = normalizeString(order?.currency_id, \"UNKNOWN\");\n const shipmentCost = roundMoney(extractShipmentCost(costs));\n const dayBucket = getLocalDateBucket(normalizeString(order?.date_created), BUSINESS_TIME_ZONE);\n\n shipmentsInspected += 1;\n incrementCount(statusCounts, shipmentStatus);\n incrementCount(substatusCounts, shipmentSubstatus);\n incrementCount(logisticTypeCounts, logisticType || \"unknown\");\n incrementCount(modeCounts, mode || \"unknown\");\n\n if (shipmentStatus === \"delivered\") {\n deliveredShipments += 1;\n }\n if (shipmentStatus === \"cancelled\") {\n cancelledShipments += 1;\n }\n if (shipmentStatus === \"not_delivered\") {\n notDeliveredShipments += 1;\n }\n\n const bucket = currencyBucket(costsByCurrency, currencyId, () => ({\n shipments: 0,\n shipments_with_cost: 0,\n zero_cost_shipments: 0,\n total_cost: 0,\n }));\n bucket.shipments += 1;\n bucket.total_cost += shipmentCost;\n if (shipmentCost > 0) {\n bucket.shipments_with_cost += 1;\n } else {\n bucket.zero_cost_shipments += 1;\n }\n\n if (dayBucket) {\n const dayMetric = dailyMetrics.get(dayBucket) ?? {\n date: dayBucket,\n shipments: 0,\n delivered_shipments: 0,\n cancelled_shipments: 0,\n not_delivered_shipments: 0,\n shipping_cost_by_currency: {},\n };\n dayMetric.shipments += 1;\n if (shipmentStatus === \"delivered\") {\n dayMetric.delivered_shipments += 1;\n }\n if (shipmentStatus === \"cancelled\") {\n dayMetric.cancelled_shipments += 1;\n }\n if (shipmentStatus === \"not_delivered\") {\n dayMetric.not_delivered_shipments += 1;\n }\n incrementCurrency(dayMetric.shipping_cost_by_currency, currencyId, shipmentCost);\n dailyMetrics.set(dayBucket, dayMetric);\n }\n\n if (responseMode === \"shipments_chunk\") {\n shipmentRows.push(\n formatCompactShipmentRow({\n orderId: normalizeScalarString(order?.id),\n shipmentId,\n status: shipmentStatus,\n substatus: shipmentSubstatus,\n logisticType,\n mode,\n currencyId,\n cost: shipmentCost,\n })\n );\n }\n }\n }\n\n for (const metrics of Object.values(costsByCurrency)) {\n metrics.total_cost = roundMoney(metrics.total_cost);\n }\n\n const metadata = buildShippingSummaryMetadata({\n total: paging.total,\n effectiveLimit,\n effectiveOffset,\n returned: allOrders.length,\n responseMode,\n pagesRequested,\n pagesSucceeded,\n pagesFailed: failedPages.length,\n failedOffsets: failedPages.map((failure) => failure.offset),\n shipmentFailures: failures.length,\n });\n\n const calculations =\n responseMode === \"calculations\"\n ? buildShippingCalculations({\n ordersTotal: allOrders.length,\n ordersWithShipping,\n shipmentsRequested: shipmentIds.length,\n shipmentsInspected,\n deliveredShipments,\n cancelledShipments,\n notDeliveredShipments,\n statusCounts,\n substatusCounts,\n logisticTypeCounts,\n modeCounts,\n costsByCurrency,\n dailyMetrics,\n metadata,\n failedPages,\n shipmentFailures: failures,\n })\n : undefined;\n\n return object(\n stripNulls({\n profile_id: profileId,\n metadata,\n shipments_schema: responseMode === \"shipments_chunk\" ? shipmentsSchema : undefined,\n shipments: responseMode === \"shipments_chunk\" ? shipmentRows : undefined,\n calculations,\n failures: failures.length > 0 ? failures : undefined,\n failed_pages: failedPages.length > 0 ? failedPages : undefined,\n })\n );\n } catch (err) {\n return error(formatMercadoLibreError(err, \"Failed to summarize MercadoLibre shipping\"));\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,50 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { formatMercadoLibreError } from "../../services/mercadolibre/mercadolibre-api.js";
4
+ import { getMercadoLibreSiteCategoriesAndListingTypes } from "../../services/mercadolibre/mercadolibre-items.js";
5
+ import { stripNulls } from "../../utils/strip-payload.js";
6
+ import { asArray, normalizeString } from "./helpers.js";
7
+ import { resolveMercadoLibreProfileOrSelection } from "./profile-resolution.js";
8
+ import { mercadolibreProfileIdSchemaField } from "./write-helpers.js";
9
+ const meliGetSiteCategoriesAndListingTypesSchema = z.object({
10
+ profileId: mercadolibreProfileIdSchemaField
11
+ });
12
+ async function meliGetSiteCategoriesAndListingTypesHandler(params) {
13
+ try {
14
+ const profileResolution = await resolveMercadoLibreProfileOrSelection(params.profileId);
15
+ if (!profileResolution.ok) {
16
+ return profileResolution.response;
17
+ }
18
+ const profileId = profileResolution.value.profileId;
19
+ const catalog = await getMercadoLibreSiteCategoriesAndListingTypes(profileId);
20
+ return object(
21
+ stripNulls({
22
+ profile_id: profileId,
23
+ site_id: catalog.siteId,
24
+ categories: asArray(catalog.categories).map((category) => ({
25
+ id: normalizeString(category.id),
26
+ name: normalizeString(category.name)
27
+ })),
28
+ listing_types: asArray(catalog.listingTypes).map((listingType) => ({
29
+ id: normalizeString(listingType.id),
30
+ name: normalizeString(listingType.name)
31
+ })),
32
+ metadata: {
33
+ site_id: catalog.siteId,
34
+ categories_count: asArray(catalog.categories).length,
35
+ listing_types_count: asArray(catalog.listingTypes).length,
36
+ pagination: "No aplica. La tool consolida dos endpoints de cat\xE1logo del sitio MLA en una sola respuesta."
37
+ }
38
+ })
39
+ );
40
+ } catch (err) {
41
+ return error(
42
+ formatMercadoLibreError(err, "Failed to fetch MercadoLibre site categories and listing types")
43
+ );
44
+ }
45
+ }
46
+ export {
47
+ meliGetSiteCategoriesAndListingTypesHandler,
48
+ meliGetSiteCategoriesAndListingTypesSchema
49
+ };
50
+ //# sourceMappingURL=get-site-categories-and-listing-types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/mercadolibre/get-site-categories-and-listing-types.ts"],
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatMercadoLibreError } from \"../../services/mercadolibre/mercadolibre-api.js\";\nimport { getMercadoLibreSiteCategoriesAndListingTypes } from \"../../services/mercadolibre/mercadolibre-items.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { asArray, normalizeString } from \"./helpers.js\";\nimport { resolveMercadoLibreProfileOrSelection } from \"./profile-resolution.js\";\nimport { mercadolibreProfileIdSchemaField } from \"./write-helpers.js\";\n\nexport const meliGetSiteCategoriesAndListingTypesSchema = z.object({\n profileId: mercadolibreProfileIdSchemaField,\n});\n\nexport async function meliGetSiteCategoriesAndListingTypesHandler(\n params: z.infer<typeof meliGetSiteCategoriesAndListingTypesSchema>\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 const catalog = await getMercadoLibreSiteCategoriesAndListingTypes(profileId);\n\n return object(\n stripNulls({\n profile_id: profileId,\n site_id: catalog.siteId,\n categories: asArray<Record<string, unknown>>(catalog.categories).map((category) => ({\n id: normalizeString(category.id),\n name: normalizeString(category.name),\n })),\n listing_types: asArray<Record<string, unknown>>(catalog.listingTypes).map((listingType) => ({\n id: normalizeString(listingType.id),\n name: normalizeString(listingType.name),\n })),\n metadata: {\n site_id: catalog.siteId,\n categories_count: asArray(catalog.categories).length,\n listing_types_count: asArray(catalog.listingTypes).length,\n pagination: \"No aplica. La tool consolida dos endpoints de cat\u00E1logo del sitio MLA en una sola respuesta.\",\n },\n })\n );\n } catch (err) {\n return error(\n formatMercadoLibreError(err, \"Failed to fetch MercadoLibre site categories and listing types\")\n );\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,+BAA+B;AACxC,SAAS,oDAAoD;AAC7D,SAAS,kBAAkB;AAC3B,SAAS,SAAS,uBAAuB;AACzC,SAAS,6CAA6C;AACtD,SAAS,wCAAwC;AAE1C,MAAM,6CAA6C,EAAE,OAAO;AAAA,EACjE,WAAW;AACb,CAAC;AAED,eAAsB,4CACpB,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;AAC1C,UAAM,UAAU,MAAM,6CAA6C,SAAS;AAE5E,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,SAAS,QAAQ;AAAA,QACjB,YAAY,QAAiC,QAAQ,UAAU,EAAE,IAAI,CAAC,cAAc;AAAA,UAClF,IAAI,gBAAgB,SAAS,EAAE;AAAA,UAC/B,MAAM,gBAAgB,SAAS,IAAI;AAAA,QACrC,EAAE;AAAA,QACF,eAAe,QAAiC,QAAQ,YAAY,EAAE,IAAI,CAAC,iBAAiB;AAAA,UAC1F,IAAI,gBAAgB,YAAY,EAAE;AAAA,UAClC,MAAM,gBAAgB,YAAY,IAAI;AAAA,QACxC,EAAE;AAAA,QACF,UAAU;AAAA,UACR,SAAS,QAAQ;AAAA,UACjB,kBAAkB,QAAQ,QAAQ,UAAU,EAAE;AAAA,UAC9C,qBAAqB,QAAQ,QAAQ,YAAY,EAAE;AAAA,UACnD,YAAY;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,wBAAwB,KAAK,gEAAgE;AAAA,IAC/F;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -13,6 +13,7 @@ export * from "./get-listing-quality.js";
13
13
  export * from "./predict-category.js";
14
14
  export * from "./get-category-requirements.js";
15
15
  export * from "./estimate-listing-fee.js";
16
+ export * from "./estimate-product-profitability.js";
16
17
  export * from "./create-item.js";
17
18
  export * from "./update-item-basic-fields.js";
18
19
  export * from "./update-item-description.js";
@@ -21,4 +22,5 @@ export * from "./pause-or-reactivate-item.js";
21
22
  export * from "./search-questions.js";
22
23
  export * from "./answer-question.js";
23
24
  export * from "./profile-resolution.js";
25
+ export * from "./get-site-categories-and-listing-types.js";
24
26
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/tools/mercadolibre/index.ts"],
4
- "sourcesContent": ["export * from \"./get-account-context.js\";\nexport * from \"./validate-connection.js\";\nexport * from \"./get-orders-summary.js\";\nexport * from \"./get-order-details.js\";\nexport * from \"./get-sales-by-item.js\";\nexport * from \"./get-sales-trend.js\";\nexport * from \"./get-shipping-summary.js\";\nexport * from \"./get-item-visits.js\";\nexport * from \"./get-store-performance.js\";\nexport * from \"./search-items.js\";\nexport * from \"./get-item-details.js\";\nexport * from \"./get-listing-quality.js\";\nexport * from \"./predict-category.js\";\nexport * from \"./get-category-requirements.js\";\nexport * from \"./estimate-listing-fee.js\";\nexport * from \"./create-item.js\";\nexport * from \"./update-item-basic-fields.js\";\nexport * from \"./update-item-description.js\";\nexport * from \"./update-item-pictures.js\";\nexport * from \"./pause-or-reactivate-item.js\";\nexport * from \"./search-questions.js\";\nexport * from \"./answer-question.js\";\nexport * from \"./profile-resolution.js\";\n"],
5
- "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
4
+ "sourcesContent": ["export * from \"./get-account-context.js\";\nexport * from \"./validate-connection.js\";\nexport * from \"./get-orders-summary.js\";\nexport * from \"./get-order-details.js\";\nexport * from \"./get-sales-by-item.js\";\nexport * from \"./get-sales-trend.js\";\nexport * from \"./get-shipping-summary.js\";\nexport * from \"./get-item-visits.js\";\nexport * from \"./get-store-performance.js\";\nexport * from \"./search-items.js\";\nexport * from \"./get-item-details.js\";\nexport * from \"./get-listing-quality.js\";\nexport * from \"./predict-category.js\";\nexport * from \"./get-category-requirements.js\";\nexport * from \"./estimate-listing-fee.js\";\nexport * from \"./estimate-product-profitability.js\";\nexport * from \"./create-item.js\";\nexport * from \"./update-item-basic-fields.js\";\nexport * from \"./update-item-description.js\";\nexport * from \"./update-item-pictures.js\";\nexport * from \"./pause-or-reactivate-item.js\";\nexport * from \"./search-questions.js\";\nexport * from \"./answer-question.js\";\nexport * from \"./profile-resolution.js\";\nexport * from \"./get-site-categories-and-listing-types.js\";\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,265 @@
1
+ import {
2
+ getMercadoLibreItem,
3
+ estimateMercadoLibreListingPrice,
4
+ searchMercadoLibreDomainDiscovery
5
+ } from "../../services/mercadolibre/mercadolibre-items.js";
6
+ import { stripNulls } from "../../utils/strip-payload.js";
7
+ import { asArray, asRecord, normalizeString, roundMoney, toNumber } from "./helpers.js";
8
+ function normalizeTags(tags) {
9
+ return tags?.map((tag) => tag.trim()).filter(Boolean).join(",");
10
+ }
11
+ function getAttributeValue(item, ids) {
12
+ const attributes = asArray(item.attributes);
13
+ for (const id of ids) {
14
+ const attribute = attributes.find((entry) => normalizeString(entry.id) === id);
15
+ if (!attribute) {
16
+ continue;
17
+ }
18
+ const valueStruct = asRecord(attribute.value_struct);
19
+ const structNumber = toNumber(valueStruct.number);
20
+ const structUnit = normalizeString(valueStruct.unit).toLowerCase();
21
+ if (structNumber > 0 && structUnit) {
22
+ return { number: structNumber, unit: structUnit, raw: normalizeString(attribute.value_name) };
23
+ }
24
+ const value = normalizeString(attribute.value_name);
25
+ if (value) {
26
+ return { raw: value };
27
+ }
28
+ }
29
+ return null;
30
+ }
31
+ function parseWeightToGrams(value) {
32
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
33
+ return value;
34
+ }
35
+ if (value && typeof value === "object") {
36
+ const record = value;
37
+ const number = toNumber(record.number);
38
+ const unit2 = normalizeString(record.unit).toLowerCase();
39
+ if (number > 0) {
40
+ if (unit2 === "kg" || unit2 === "kilogram" || unit2 === "kilograms") {
41
+ return roundMoney(number * 1e3);
42
+ }
43
+ if (unit2 === "g" || unit2 === "gr" || unit2 === "gram" || unit2 === "grams") {
44
+ return roundMoney(number);
45
+ }
46
+ }
47
+ }
48
+ if (typeof value !== "string") {
49
+ return void 0;
50
+ }
51
+ const normalized = value.trim().toLowerCase().replace(",", ".").replace(/\s+/g, " ");
52
+ const match = normalized.match(/([\d.]+)\s*(kg|kgs|kilogramos?|g|gr|gramos?)\b/);
53
+ if (!match) {
54
+ return void 0;
55
+ }
56
+ const amount = Number(match[1]);
57
+ if (!Number.isFinite(amount) || amount <= 0) {
58
+ return void 0;
59
+ }
60
+ const unit = match[2];
61
+ return unit.startsWith("kg") || unit.startsWith("kilogram") ? roundMoney(amount * 1e3) : roundMoney(amount);
62
+ }
63
+ function extractBillableWeightFromItem(item) {
64
+ const candidate = getAttributeValue(item, [
65
+ "SELLER_PACKAGE_WEIGHT",
66
+ "PACKAGE_WEIGHT",
67
+ "WEIGHT"
68
+ ]);
69
+ if (!candidate) {
70
+ return void 0;
71
+ }
72
+ return parseWeightToGrams(
73
+ "number" in candidate && "unit" in candidate ? { number: candidate.number, unit: candidate.unit } : candidate.raw
74
+ );
75
+ }
76
+ function extractSellerSku(item) {
77
+ return normalizeString(item.seller_custom_field) || normalizeString(getAttributeValue(item, ["SELLER_SKU"])?.raw);
78
+ }
79
+ function buildMissingParams(usedParams) {
80
+ const missing = [];
81
+ if (!usedParams.price || usedParams.price <= 0) {
82
+ missing.push("price");
83
+ }
84
+ if (!usedParams.category_id) {
85
+ missing.push("categoryId");
86
+ }
87
+ if (!usedParams.listing_type_id) {
88
+ missing.push("listingTypeId");
89
+ }
90
+ if (!usedParams.shipping_mode) {
91
+ missing.push("shippingMode");
92
+ }
93
+ if (!usedParams.logistic_type) {
94
+ missing.push("logisticType");
95
+ }
96
+ if (!usedParams.billable_weight || usedParams.billable_weight <= 0) {
97
+ missing.push("billableWeight");
98
+ }
99
+ return missing;
100
+ }
101
+ function buildGuidedQuestions(missingParams) {
102
+ const byField = {
103
+ price: {
104
+ field: "price",
105
+ question: "\xBFA qu\xE9 precio quer\xE9s cotizar la publicaci\xF3n?",
106
+ impact: "MercadoLibre necesita precio para calcular cargos."
107
+ },
108
+ categoryId: {
109
+ field: "categoryId",
110
+ question: "\xBFQu\xE9 categor\xEDa de MercadoLibre corresponde al producto?",
111
+ impact: "La categor\xEDa puede cambiar el porcentaje y costo fijo de comisi\xF3n."
112
+ },
113
+ listingTypeId: {
114
+ field: "listingTypeId",
115
+ question: "\xBFQuer\xE9s cotizar Cl\xE1sica (gold_special), Premium (gold_pro) u otro tipo?",
116
+ impact: "El tipo de publicaci\xF3n cambia exposici\xF3n, financiaci\xF3n y comisi\xF3n."
117
+ },
118
+ shippingMode: {
119
+ field: "shippingMode",
120
+ question: "\xBFQu\xE9 modo de env\xEDo aplica, por ejemplo me2?",
121
+ impact: "En MLA mejora el c\xE1lculo de costo fijo y env\xEDo asociado."
122
+ },
123
+ logisticType: {
124
+ field: "logisticType",
125
+ question: "\xBFQu\xE9 log\xEDstica aplica, por ejemplo fulfillment, drop_off o xd_drop_off?",
126
+ impact: "La log\xEDstica afecta el c\xE1lculo preciso de cargos por venta."
127
+ },
128
+ billableWeight: {
129
+ field: "billableWeight",
130
+ question: "\xBFCu\xE1l es el peso facturable del paquete en gramos?",
131
+ impact: "MercadoLibre Argentina lo usa para calcular con precisi\xF3n cargos asociados."
132
+ }
133
+ };
134
+ return missingParams.map((field) => byField[field]).filter(Boolean);
135
+ }
136
+ function inferPrecision(missingParams) {
137
+ if (missingParams.length === 0) {
138
+ return "high";
139
+ }
140
+ const criticalMissing = missingParams.filter(
141
+ (field) => ["price", "categoryId", "listingTypeId"].includes(field)
142
+ );
143
+ return criticalMissing.length > 0 ? "low" : "medium";
144
+ }
145
+ function normalizeQuoteResponse(input) {
146
+ if (Array.isArray(input)) {
147
+ return input;
148
+ }
149
+ if (input && typeof input === "object") {
150
+ return [input];
151
+ }
152
+ return [];
153
+ }
154
+ function normalizeQuote(quote, price) {
155
+ const saleFeeDetails = asRecord(quote.sale_fee_details);
156
+ const listingFeeDetails = asRecord(quote.listing_fee_details);
157
+ const saleFeeAmount = roundMoney(toNumber(quote.sale_fee_amount));
158
+ const listingFeeAmount = roundMoney(toNumber(quote.listing_fee_amount));
159
+ return stripNulls({
160
+ listing_type_id: normalizeString(quote.listing_type_id),
161
+ listing_type_name: normalizeString(quote.listing_type_name),
162
+ currency_id: normalizeString(quote.currency_id, "ARS"),
163
+ listing_exposure: normalizeString(quote.listing_exposure),
164
+ price,
165
+ listing_fee_amount: listingFeeAmount,
166
+ listing_fee_details: {
167
+ fixed_fee: roundMoney(toNumber(listingFeeDetails.fixed_fee)),
168
+ gross_amount: roundMoney(toNumber(listingFeeDetails.gross_amount))
169
+ },
170
+ sale_fee_amount: saleFeeAmount,
171
+ sale_fee_details: {
172
+ financing_add_on_fee: roundMoney(toNumber(saleFeeDetails.financing_add_on_fee)),
173
+ fixed_fee: roundMoney(toNumber(saleFeeDetails.fixed_fee)),
174
+ gross_amount: roundMoney(toNumber(saleFeeDetails.gross_amount)),
175
+ meli_percentage_fee: toNumber(saleFeeDetails.meli_percentage_fee),
176
+ percentage_fee: toNumber(saleFeeDetails.percentage_fee)
177
+ },
178
+ net_after_sale_fee: roundMoney(price - saleFeeAmount),
179
+ net_after_total_meli_fee: roundMoney(price - saleFeeAmount - listingFeeAmount),
180
+ requires_picture: quote.requires_picture,
181
+ free_relist: quote.free_relist,
182
+ stop_time: normalizeString(quote.stop_time)
183
+ });
184
+ }
185
+ async function buildMercadoLibreListingFeeEstimate(params) {
186
+ const item = params.itemId ? await getMercadoLibreItem(params.profileId, params.itemId) : void 0;
187
+ const shipping = asRecord(item?.shipping);
188
+ const source = item ? Object.values({
189
+ price: params.price,
190
+ categoryId: params.categoryId,
191
+ listingTypeId: params.listingTypeId,
192
+ shippingMode: params.shippingMode,
193
+ logisticType: params.logisticType,
194
+ billableWeight: params.billableWeight
195
+ }).some((value) => value !== void 0 && value !== "") ? "mixed" : "item" : "manual";
196
+ const price = params.price ?? toNumber(item?.price);
197
+ const usedParams = stripNulls({
198
+ price: price > 0 ? price : void 0,
199
+ category_id: params.categoryId || normalizeString(item?.category_id),
200
+ listing_type_id: params.listingTypeId || normalizeString(item?.listing_type_id),
201
+ shipping_mode: params.shippingMode || normalizeString(shipping.mode),
202
+ logistic_type: params.logisticType || normalizeString(shipping.logistic_type),
203
+ billable_weight: params.billableWeight ?? (item ? extractBillableWeightFromItem(item) : void 0),
204
+ currency_id: params.currencyId || normalizeString(item?.currency_id, "ARS"),
205
+ tags: normalizeTags(params.tags)
206
+ });
207
+ const missingParams = buildMissingParams(usedParams);
208
+ const candidates = params.query && !usedParams.category_id ? await searchMercadoLibreDomainDiscovery(params.profileId, params.query, 5, "MLA") : [];
209
+ const context = stripNulls({
210
+ item,
211
+ item_id: params.itemId,
212
+ title: normalizeString(item?.title),
213
+ seller_sku: item ? extractSellerSku(item) : void 0,
214
+ source,
215
+ used_params: usedParams,
216
+ missing_params: missingParams,
217
+ guided_questions: buildGuidedQuestions(missingParams),
218
+ precision: inferPrecision(missingParams),
219
+ category_candidates: asArray(candidates).map((candidate) => ({
220
+ category_id: normalizeString(candidate.category_id),
221
+ category_name: normalizeString(candidate.category_name),
222
+ domain_id: normalizeString(candidate.domain_id),
223
+ domain_name: normalizeString(candidate.domain_name),
224
+ attributes_matched: toNumber(candidate.attributes_matched)
225
+ }))
226
+ });
227
+ if (!usedParams.price || usedParams.price <= 0) {
228
+ return {
229
+ profile_id: params.profileId,
230
+ purpose: "Cotiza cargos de MercadoLibre; no calcula rentabilidad de negocio.",
231
+ context,
232
+ quotes: [],
233
+ calculation_status: context.category_candidates?.length ? "guidance_only" : "needs_price"
234
+ };
235
+ }
236
+ const apiParams = stripNulls({
237
+ price: usedParams.price,
238
+ currency_id: usedParams.currency_id || "ARS",
239
+ category_id: usedParams.category_id,
240
+ listing_type_id: usedParams.listing_type_id,
241
+ shipping_mode: usedParams.shipping_mode,
242
+ logistic_type: usedParams.logistic_type,
243
+ billable_weight: usedParams.billable_weight,
244
+ tags: usedParams.tags
245
+ });
246
+ const rawQuotes = await estimateMercadoLibreListingPrice(params.profileId, apiParams);
247
+ const quotes = normalizeQuoteResponse(rawQuotes).map(
248
+ (quote) => normalizeQuote(quote, usedParams.price)
249
+ );
250
+ const selectedQuote = quotes.find((quote) => quote.listing_type_id === usedParams.listing_type_id) ?? quotes[0];
251
+ return stripNulls({
252
+ profile_id: params.profileId,
253
+ purpose: "Cotiza cargos de MercadoLibre; no calcula rentabilidad de negocio.",
254
+ context,
255
+ quotes,
256
+ selected_quote: selectedQuote,
257
+ calculation_status: "quoted"
258
+ });
259
+ }
260
+ export {
261
+ buildMercadoLibreListingFeeEstimate,
262
+ extractBillableWeightFromItem,
263
+ parseWeightToGrams
264
+ };
265
+ //# sourceMappingURL=listing-fee-helpers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/mercadolibre/listing-fee-helpers.ts"],
4
+ "sourcesContent": ["import {\n getMercadoLibreItem,\n estimateMercadoLibreListingPrice,\n searchMercadoLibreDomainDiscovery,\n} from \"../../services/mercadolibre/mercadolibre-items.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { asArray, asRecord, normalizeString, roundMoney, toNumber } from \"./helpers.js\";\n\nexport type PrecisionLevel = \"low\" | \"medium\" | \"high\";\n\nexport interface ListingFeeInput {\n profileId: string;\n itemId?: string;\n query?: string;\n price?: number;\n categoryId?: string;\n listingTypeId?: string;\n shippingMode?: string;\n logisticType?: string;\n billableWeight?: number;\n currencyId?: string;\n tags?: string[];\n}\n\nexport interface ListingFeeResolvedContext {\n item?: Record<string, unknown>;\n item_id?: string;\n title?: string;\n seller_sku?: string;\n source: \"item\" | \"manual\" | \"mixed\";\n used_params: {\n price?: number;\n category_id?: string;\n listing_type_id?: string;\n shipping_mode?: string;\n logistic_type?: string;\n billable_weight?: number;\n currency_id?: string;\n tags?: string;\n };\n missing_params: string[];\n guided_questions: Array<{\n field: string;\n question: string;\n impact: string;\n }>;\n precision: PrecisionLevel;\n category_candidates?: Array<{\n category_id: string;\n category_name: string;\n domain_id: string;\n domain_name: string;\n attributes_matched: number;\n }>;\n}\n\nexport interface ListingFeeQuote {\n listing_type_id: string;\n listing_type_name: string;\n currency_id: string;\n listing_exposure?: string;\n price: number;\n listing_fee_amount: number;\n listing_fee_details: {\n fixed_fee: number;\n gross_amount: number;\n };\n sale_fee_amount: number;\n sale_fee_details: {\n financing_add_on_fee: number;\n fixed_fee: number;\n gross_amount: number;\n meli_percentage_fee: number;\n percentage_fee: number;\n };\n net_after_sale_fee: number;\n net_after_total_meli_fee: number;\n requires_picture?: boolean;\n free_relist?: unknown;\n stop_time?: string;\n}\n\nexport interface ListingFeeEstimateResult {\n profile_id: string;\n purpose: string;\n context: ListingFeeResolvedContext;\n quotes: ListingFeeQuote[];\n selected_quote?: ListingFeeQuote;\n calculation_status: \"quoted\" | \"needs_price\" | \"guidance_only\";\n}\n\nfunction normalizeTags(tags?: string[]) {\n return tags?.map((tag) => tag.trim()).filter(Boolean).join(\",\");\n}\n\nfunction getAttributeValue(item: Record<string, unknown>, ids: string[]) {\n const attributes = asArray<Record<string, unknown>>(item.attributes);\n for (const id of ids) {\n const attribute = attributes.find((entry) => normalizeString(entry.id) === id);\n if (!attribute) {\n continue;\n }\n\n const valueStruct = asRecord(attribute.value_struct);\n const structNumber = toNumber(valueStruct.number);\n const structUnit = normalizeString(valueStruct.unit).toLowerCase();\n if (structNumber > 0 && structUnit) {\n return { number: structNumber, unit: structUnit, raw: normalizeString(attribute.value_name) };\n }\n\n const value = normalizeString(attribute.value_name);\n if (value) {\n return { raw: value };\n }\n }\n\n return null;\n}\n\nexport function parseWeightToGrams(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n return value;\n }\n\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const number = toNumber(record.number);\n const unit = normalizeString(record.unit).toLowerCase();\n if (number > 0) {\n if (unit === \"kg\" || unit === \"kilogram\" || unit === \"kilograms\") {\n return roundMoney(number * 1000);\n }\n if (unit === \"g\" || unit === \"gr\" || unit === \"gram\" || unit === \"grams\") {\n return roundMoney(number);\n }\n }\n }\n\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const normalized = value\n .trim()\n .toLowerCase()\n .replace(\",\", \".\")\n .replace(/\\s+/g, \" \");\n const match = normalized.match(/([\\d.]+)\\s*(kg|kgs|kilogramos?|g|gr|gramos?)\\b/);\n if (!match) {\n return undefined;\n }\n\n const amount = Number(match[1]);\n if (!Number.isFinite(amount) || amount <= 0) {\n return undefined;\n }\n\n const unit = match[2];\n return unit.startsWith(\"kg\") || unit.startsWith(\"kilogram\")\n ? roundMoney(amount * 1000)\n : roundMoney(amount);\n}\n\nexport function extractBillableWeightFromItem(item: Record<string, unknown>): number | undefined {\n const candidate = getAttributeValue(item, [\n \"SELLER_PACKAGE_WEIGHT\",\n \"PACKAGE_WEIGHT\",\n \"WEIGHT\",\n ]);\n if (!candidate) {\n return undefined;\n }\n\n return parseWeightToGrams(\n \"number\" in candidate && \"unit\" in candidate\n ? { number: candidate.number, unit: candidate.unit }\n : candidate.raw\n );\n}\n\nfunction extractSellerSku(item: Record<string, unknown>) {\n return normalizeString(item.seller_custom_field) ||\n normalizeString(getAttributeValue(item, [\"SELLER_SKU\"])?.raw);\n}\n\nfunction buildMissingParams(usedParams: ListingFeeResolvedContext[\"used_params\"]) {\n const missing: string[] = [];\n if (!usedParams.price || usedParams.price <= 0) {\n missing.push(\"price\");\n }\n if (!usedParams.category_id) {\n missing.push(\"categoryId\");\n }\n if (!usedParams.listing_type_id) {\n missing.push(\"listingTypeId\");\n }\n if (!usedParams.shipping_mode) {\n missing.push(\"shippingMode\");\n }\n if (!usedParams.logistic_type) {\n missing.push(\"logisticType\");\n }\n if (!usedParams.billable_weight || usedParams.billable_weight <= 0) {\n missing.push(\"billableWeight\");\n }\n return missing;\n}\n\nfunction buildGuidedQuestions(missingParams: string[]) {\n const byField: Record<string, { field: string; question: string; impact: string }> = {\n price: {\n field: \"price\",\n question: \"\u00BFA qu\u00E9 precio quer\u00E9s cotizar la publicaci\u00F3n?\",\n impact: \"MercadoLibre necesita precio para calcular cargos.\",\n },\n categoryId: {\n field: \"categoryId\",\n question: \"\u00BFQu\u00E9 categor\u00EDa de MercadoLibre corresponde al producto?\",\n impact: \"La categor\u00EDa puede cambiar el porcentaje y costo fijo de comisi\u00F3n.\",\n },\n listingTypeId: {\n field: \"listingTypeId\",\n question: \"\u00BFQuer\u00E9s cotizar Cl\u00E1sica (gold_special), Premium (gold_pro) u otro tipo?\",\n impact: \"El tipo de publicaci\u00F3n cambia exposici\u00F3n, financiaci\u00F3n y comisi\u00F3n.\",\n },\n shippingMode: {\n field: \"shippingMode\",\n question: \"\u00BFQu\u00E9 modo de env\u00EDo aplica, por ejemplo me2?\",\n impact: \"En MLA mejora el c\u00E1lculo de costo fijo y env\u00EDo asociado.\",\n },\n logisticType: {\n field: \"logisticType\",\n question: \"\u00BFQu\u00E9 log\u00EDstica aplica, por ejemplo fulfillment, drop_off o xd_drop_off?\",\n impact: \"La log\u00EDstica afecta el c\u00E1lculo preciso de cargos por venta.\",\n },\n billableWeight: {\n field: \"billableWeight\",\n question: \"\u00BFCu\u00E1l es el peso facturable del paquete en gramos?\",\n impact: \"MercadoLibre Argentina lo usa para calcular con precisi\u00F3n cargos asociados.\",\n },\n };\n\n return missingParams.map((field) => byField[field]).filter(Boolean);\n}\n\nfunction inferPrecision(missingParams: string[]): PrecisionLevel {\n if (missingParams.length === 0) {\n return \"high\";\n }\n\n const criticalMissing = missingParams.filter((field) =>\n [\"price\", \"categoryId\", \"listingTypeId\"].includes(field)\n );\n return criticalMissing.length > 0 ? \"low\" : \"medium\";\n}\n\nfunction normalizeQuoteResponse(input: unknown): Record<string, unknown>[] {\n if (Array.isArray(input)) {\n return input as Record<string, unknown>[];\n }\n\n if (input && typeof input === \"object\") {\n return [input as Record<string, unknown>];\n }\n\n return [];\n}\n\nfunction normalizeQuote(quote: Record<string, unknown>, price: number): ListingFeeQuote {\n const saleFeeDetails = asRecord(quote.sale_fee_details);\n const listingFeeDetails = asRecord(quote.listing_fee_details);\n const saleFeeAmount = roundMoney(toNumber(quote.sale_fee_amount));\n const listingFeeAmount = roundMoney(toNumber(quote.listing_fee_amount));\n\n return stripNulls({\n listing_type_id: normalizeString(quote.listing_type_id),\n listing_type_name: normalizeString(quote.listing_type_name),\n currency_id: normalizeString(quote.currency_id, \"ARS\"),\n listing_exposure: normalizeString(quote.listing_exposure),\n price,\n listing_fee_amount: listingFeeAmount,\n listing_fee_details: {\n fixed_fee: roundMoney(toNumber(listingFeeDetails.fixed_fee)),\n gross_amount: roundMoney(toNumber(listingFeeDetails.gross_amount)),\n },\n sale_fee_amount: saleFeeAmount,\n sale_fee_details: {\n financing_add_on_fee: roundMoney(toNumber(saleFeeDetails.financing_add_on_fee)),\n fixed_fee: roundMoney(toNumber(saleFeeDetails.fixed_fee)),\n gross_amount: roundMoney(toNumber(saleFeeDetails.gross_amount)),\n meli_percentage_fee: toNumber(saleFeeDetails.meli_percentage_fee),\n percentage_fee: toNumber(saleFeeDetails.percentage_fee),\n },\n net_after_sale_fee: roundMoney(price - saleFeeAmount),\n net_after_total_meli_fee: roundMoney(price - saleFeeAmount - listingFeeAmount),\n requires_picture: quote.requires_picture,\n free_relist: quote.free_relist,\n stop_time: normalizeString(quote.stop_time),\n }) as ListingFeeQuote;\n}\n\nexport async function buildMercadoLibreListingFeeEstimate(\n params: ListingFeeInput\n): Promise<ListingFeeEstimateResult> {\n const item = params.itemId ? await getMercadoLibreItem(params.profileId, params.itemId) : undefined;\n const shipping = asRecord(item?.shipping);\n const source: ListingFeeResolvedContext[\"source\"] = item\n ? Object.values({\n price: params.price,\n categoryId: params.categoryId,\n listingTypeId: params.listingTypeId,\n shippingMode: params.shippingMode,\n logisticType: params.logisticType,\n billableWeight: params.billableWeight,\n }).some((value) => value !== undefined && value !== \"\")\n ? \"mixed\"\n : \"item\"\n : \"manual\";\n\n const price = params.price ?? toNumber(item?.price);\n const usedParams = stripNulls({\n price: price > 0 ? price : undefined,\n category_id: params.categoryId || normalizeString(item?.category_id),\n listing_type_id: params.listingTypeId || normalizeString(item?.listing_type_id),\n shipping_mode: params.shippingMode || normalizeString(shipping.mode),\n logistic_type: params.logisticType || normalizeString(shipping.logistic_type),\n billable_weight: params.billableWeight ?? (item ? extractBillableWeightFromItem(item) : undefined),\n currency_id: params.currencyId || normalizeString(item?.currency_id, \"ARS\"),\n tags: normalizeTags(params.tags),\n });\n\n const missingParams = buildMissingParams(usedParams);\n const candidates =\n params.query && !usedParams.category_id\n ? await searchMercadoLibreDomainDiscovery(params.profileId, params.query, 5, \"MLA\")\n : [];\n const context: ListingFeeResolvedContext = stripNulls({\n item,\n item_id: params.itemId,\n title: normalizeString(item?.title),\n seller_sku: item ? extractSellerSku(item) : undefined,\n source,\n used_params: usedParams,\n missing_params: missingParams,\n guided_questions: buildGuidedQuestions(missingParams),\n precision: inferPrecision(missingParams),\n category_candidates: asArray<Record<string, unknown>>(candidates).map((candidate) => ({\n category_id: normalizeString(candidate.category_id),\n category_name: normalizeString(candidate.category_name),\n domain_id: normalizeString(candidate.domain_id),\n domain_name: normalizeString(candidate.domain_name),\n attributes_matched: toNumber(candidate.attributes_matched),\n })),\n }) as ListingFeeResolvedContext;\n\n if (!usedParams.price || usedParams.price <= 0) {\n return {\n profile_id: params.profileId,\n purpose: \"Cotiza cargos de MercadoLibre; no calcula rentabilidad de negocio.\",\n context,\n quotes: [],\n calculation_status: context.category_candidates?.length ? \"guidance_only\" : \"needs_price\",\n };\n }\n\n const apiParams = stripNulls({\n price: usedParams.price,\n currency_id: usedParams.currency_id || \"ARS\",\n category_id: usedParams.category_id,\n listing_type_id: usedParams.listing_type_id,\n shipping_mode: usedParams.shipping_mode,\n logistic_type: usedParams.logistic_type,\n billable_weight: usedParams.billable_weight,\n tags: usedParams.tags,\n });\n const rawQuotes = await estimateMercadoLibreListingPrice(params.profileId, apiParams);\n const quotes = normalizeQuoteResponse(rawQuotes).map((quote) =>\n normalizeQuote(quote, usedParams.price as number)\n );\n const selectedQuote =\n quotes.find((quote) => quote.listing_type_id === usedParams.listing_type_id) ?? quotes[0];\n\n return stripNulls({\n profile_id: params.profileId,\n purpose: \"Cotiza cargos de MercadoLibre; no calcula rentabilidad de negocio.\",\n context,\n quotes,\n selected_quote: selectedQuote,\n calculation_status: \"quoted\",\n }) as ListingFeeEstimateResult;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["unit"]
7
+ }