{"_id":"@codemind.ec/medusa-plugin-contifico","_rev":"3-610f2f5c9035d234edae8e2c95af64d6","name":"@codemind.ec/medusa-plugin-contifico","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@codemind.ec/medusa-plugin-contifico","version":"1.0.0","keywords":["medusa","medusa-plugin","medusa-v2","plugin","contifico","erp","ecuador","codemind","kollor"],"author":{"url":"https://codemind.ec","name":"Kollor","email":"dev@codemind.ec"},"license":"MIT","_id":"@codemind.ec/medusa-plugin-contifico@1.0.0","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"dist":{"shasum":"05c62a03a243a2114772e844caba8b1dc0500597","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-contifico/-/medusa-plugin-contifico-1.0.0.tgz","fileCount":122,"integrity":"sha512-rE/CJC8Qk1IzzG12P1gtAo4S5isHp6ojOD4O9j0/jlkOlrtoZryzRCuSH9oXV0HS0WnQQxMtromQMZ4HrBa07Q==","signatures":[{"sig":"MEUCIDuTcZ6TijuAeupuXMU7rstupkNZ0rY2yRf3Arvl0088AiEAwwGQQoBld/cRtJq2U/p6GUFfijS5NVhYySCk7vDLoaM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1369236},"engines":{"node":">=20"},"exports":{"./*":"./.medusa/server/src/*.js","./admin":{"import":"./.medusa/server/src/admin/index.mjs","default":"./.medusa/server/src/admin/index.js","require":"./.medusa/server/src/admin/index.js"},"./modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./providers/*":"./.medusa/server/src/providers/*/index.js","./package.json":"./package.json","./.medusa/server/src/modules/*":"./.medusa/server/src/modules/*/index.js"},"gitHead":"e8f515a4d4fbf47a3ebf48140c0ef2f5ea88c670","scripts":{"dev":"medusa plugin:develop","test":"vitest run","build":"medusa plugin:build","prepublishOnly":"medusa plugin:build"},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"_npmVersion":"10.9.2","description":"Medusa v2 plugin for Contifico ERP integration — product sync, stock management, customer mapping, and electronic invoicing for Ecuador.","directories":{},"_nodeVersion":"22.15.1","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.9","devDependencies":{"vite":"^5.4.14","yalc":"^1.0.0-pre.53","react":"^18.3.1","vitest":"^2.1.8","ts-node":"^10.9.2","@swc/core":"^1.7.28","react-dom":"^18.3.1","prop-types":"^15.8.1","typescript":"^5","@types/node":"^20","@medusajs/ui":"^4.1.3","@types/react":"^18.3.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@types/react-dom":"^18.3.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"peerDependencies":{"@medusajs/ui":"^4.1.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"_npmOperationalInternal":{"tmp":"tmp/medusa-plugin-contifico_1.0.0_1774052803034_0.9623506879417336","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@codemind.ec/medusa-plugin-contifico","version":"1.0.1","keywords":["medusa","medusa-plugin","medusa-v2","plugin","contifico","erp","ecuador","codemind","kollor"],"author":{"url":"https://codemind.ec","name":"Kollor","email":"dev@codemind.ec"},"license":"MIT","_id":"@codemind.ec/medusa-plugin-contifico@1.0.1","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"dist":{"shasum":"ca0890b9f745676767426d1054fbcc03bbda7ff6","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-contifico/-/medusa-plugin-contifico-1.0.1.tgz","fileCount":123,"integrity":"sha512-XykMet3uwCY5VMgHYB8RoY5bz+Pyu4ubKZpV00m0u4V0E6yNxd4Kl6QMPli9hJwwnw3GaSXyAZ0s2NX1srxoWw==","signatures":[{"sig":"MEYCIQCGnpedCxkUuVR8dOCq3B0MTsFj7iGasyjIDLal4NLqLgIhALvMQIYc/iS/Jsu019HdKvvZ/2dD0ZED15hOSLPALyAx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1376066},"_from":"file:codemind.ec-medusa-plugin-contifico-1.0.1.tgz","engines":{"node":">=20"},"exports":{"./admin":{"import":"./.medusa/server/src/admin/index.mjs","default":"./.medusa/server/src/admin/index.js","require":"./.medusa/server/src/admin/index.js"},"./contifico":"./.medusa/server/src/modules/contifico/index.js","./modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./package.json":"./package.json","./modules/contifico":"./.medusa/server/src/modules/contifico/index.js"},"scripts":{"dev":"medusa plugin:develop","test":"vitest run","build":"medusa plugin:build"},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"_resolved":"C:\\Users\\isai_\\AppData\\Local\\Temp\\a951f62b8426f5c8dc4f494c764fc523\\codemind.ec-medusa-plugin-contifico-1.0.1.tgz","_integrity":"sha512-XykMet3uwCY5VMgHYB8RoY5bz+Pyu4ubKZpV00m0u4V0E6yNxd4Kl6QMPli9hJwwnw3GaSXyAZ0s2NX1srxoWw==","_npmVersion":"10.9.2","description":"Medusa v2 plugin for Contifico ERP integration — product sync, stock management, customer mapping, and electronic invoicing for Ecuador.","directories":{},"_nodeVersion":"22.15.1","_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.14","yalc":"^1.0.0-pre.53","react":"^18.3.1","vitest":"^2.1.8","ts-node":"^10.9.2","@swc/core":"^1.7.28","react-dom":"^18.3.1","prop-types":"^15.8.1","typescript":"^5","@types/node":"^20","@medusajs/ui":"^4.1.3","@types/react":"^18.3.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@types/react-dom":"^18.3.0","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"peerDependencies":{"@medusajs/ui":"^4.1.3","@medusajs/cli":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/admin-sdk":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/admin-shared":"2.13.3"},"_npmOperationalInternal":{"tmp":"tmp/medusa-plugin-contifico_1.0.1_1774066501500_0.7852431947648106","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@codemind.ec/medusa-plugin-contifico","description":"Medusa v2 plugin for Contifico ERP integration — product sync, stock management, customer mapping, and electronic invoicing for Ecuador.","version":"1.0.2","author":{"name":"Kollor","email":"dev@codemind.ec","url":"https://codemind.ec"},"license":"MIT","exports":{"./package.json":"./package.json","./contifico":"./.medusa/server/src/modules/contifico/index.js","./modules/contifico":"./.medusa/server/src/modules/contifico/index.js","./modules/*":"./.medusa/server/src/modules/*/index.js","./.medusa/server/src/modules/*":"./.medusa/server/src/modules/*/index.js","./workflows":"./.medusa/server/src/workflows/index.js","./admin":{"import":"./.medusa/server/src/admin/index.mjs","require":"./.medusa/server/src/admin/index.js","default":"./.medusa/server/src/admin/index.js"}},"scripts":{"build":"medusa plugin:build","dev":"medusa plugin:develop","test":"vitest run","prepublishOnly":"medusa plugin:build"},"devDependencies":{"@medusajs/admin-sdk":"2.13.3","@medusajs/admin-shared":"2.13.3","@medusajs/cli":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/ui":"^4.1.3","@swc/core":"^1.7.28","@types/node":"^20","@types/react":"^18.3.3","@types/react-dom":"^18.3.0","prop-types":"^15.8.1","react":"^18.3.1","react-dom":"^18.3.1","ts-node":"^10.9.2","typescript":"^5","vite":"^5.4.14","vitest":"^2.1.8","yalc":"^1.0.0-pre.53"},"engines":{"node":">=20"},"keywords":["medusa","medusa-plugin","medusa-v2","plugin","contifico","erp","ecuador","codemind","kollor"],"packageManager":"pnpm@9.15.9","peerDependencies":{"@medusajs/admin-sdk":"2.13.3","@medusajs/admin-shared":"2.13.3","@medusajs/cli":"2.13.3","@medusajs/framework":"2.13.3","@medusajs/icons":"^2.13.3","@medusajs/medusa":"2.13.3","@medusajs/test-utils":"2.13.3","@medusajs/ui":"^4.1.3"},"_id":"@codemind.ec/medusa-plugin-contifico@1.0.2","gitHead":"4f7974c7a642ed7ecc3c4ff9105b6366ea70b238","_nodeVersion":"22.15.1","_npmVersion":"10.9.2","dist":{"integrity":"sha512-POh14R3knnW4rO0ZiRNB32J0fbUyOG9qhNCq/Raj7y/L4XEC5W+I11owizBTq3oi+ThAsrzXrMKa1vh3KLdAcw==","shasum":"e10aa5852d16017c4e12c0f3b254a3926de0ef3b","tarball":"https://registry.npmjs.org/@codemind.ec/medusa-plugin-contifico/-/medusa-plugin-contifico-1.0.2.tgz","fileCount":123,"unpackedSize":1378935,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHk8DrK/9aFsoFnxgG5Yh0+iHTgtHosQSu4rbANd7pZKAiBiSth0X5uN8CsJq8TD/Fqdb38HfmGJK2wx8nwvcJPh8w=="}]},"_npmUser":{"name":"kollor","email":"isai.tobar@hotmail.com"},"directories":{},"maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/medusa-plugin-contifico_1.0.2_1774073481963_0.7401224008289082"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T00:26:42.851Z","modified":"2026-03-21T06:11:22.265Z","1.0.0":"2026-03-21T00:26:43.190Z","1.0.1":"2026-03-21T04:15:01.673Z","1.0.2":"2026-03-21T06:11:22.139Z"},"author":{"name":"Kollor","email":"dev@codemind.ec","url":"https://codemind.ec"},"license":"MIT","keywords":["medusa","medusa-plugin","medusa-v2","plugin","contifico","erp","ecuador","codemind","kollor"],"description":"Medusa v2 plugin for Contifico ERP integration — product sync, stock management, customer mapping, and electronic invoicing for Ecuador.","maintainers":[{"name":"kollor","email":"isai.tobar@hotmail.com"}],"readme":"# @codemind.ec/medusa-plugin-contifico\r\n\r\nMedusa v2 plugin for **Contífico ERP** integration — product & stock sync, customer mapping, weighted pricing strategies, and automated electronic invoicing for Ecuador.\r\n\r\n[![npm version](https://img.shields.io/npm/v/@codemind.ec/medusa-plugin-contifico.svg)](https://www.npmjs.com/package/@codemind.ec/medusa-plugin-contifico)\r\n[![Medusa v2](https://img.shields.io/badge/medusa-v2-blueviolet)](https://docs.medusajs.com)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n---\r\n\r\n## Features\r\n\r\n- **Product synchronization** — import products and categories from Contífico, with automatic variant creation.\r\n- **Stock synchronization** — real-time inventory levels from Contífico warehouses (`bodegas`).\r\n- **Customer mapping** — match and sync customers between Medusa and Contífico.\r\n- **Weighted pricing** — pluggable strategies for weight-based product pricing (e.g., products sold by weight in grams/kg).\r\n- **Electronic invoicing** — automatic creation of pre-invoices (`PRE`) on order placement and invoices (`FAC`) on payment capture.\r\n- **Admin UI** — full dashboard for configuration, diagnostics, sync triggers, invoice previews, and linked product management.\r\n- **Observability** — correlation IDs, structured logs, and sync audit trail.\r\n\r\n---\r\n\r\n## Prerequisites\r\n\r\n| Requirement | Version |\r\n|-------------|---------|\r\n| Node.js     | >= 20   |\r\n| Medusa      | >= 2.4.0 |\r\n| Contífico account | API key required |\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @codemind.ec/medusa-plugin-contifico\r\n# or\r\npnpm add @codemind.ec/medusa-plugin-contifico\r\n```\r\n\r\n---\r\n\r\n## Configuration\r\n\r\nAdd the plugin and its module to your `medusa-config.ts`:\r\n\r\n```typescript\r\nimport { defineConfig } from \"@medusajs/framework/utils\"\r\n\r\nexport default defineConfig({\r\n  // ...\r\n  modules: [\r\n    {\r\n      resolve: \"@codemind.ec/medusa-plugin-contifico/contifico\",\r\n      definition: { isQueryable: true },\r\n    },\r\n  ],\r\n  plugins: [\r\n    {\r\n      resolve: \"@codemind.ec/medusa-plugin-contifico\",\r\n      options: {},\r\n    },\r\n  ],\r\n})\r\n```\r\n\r\n> **Nota:** El módulo se registra por separado en `modules[]` con `isQueryable: true` para que sea accesible desde el query graph de Medusa. La entrada en `plugins[]` carga admin UI, API routes, subscribers y links.\r\n\r\n### Environment Variables\r\n\r\n| Variable | Required | Description |\r\n|----------|----------|-------------|\r\n| `CONTIFICO_API_KEY` | Yes | Contífico API key |\r\n| `CONTIFICO_API_POS` | For invoicing | Point-of-sale identifier for `FAC` / `PRE` |\r\n| `CONTIFICO_URL` | No | API base URL (default: `https://api.contifico.com`) |\r\n\r\n---\r\n\r\n## Architecture\r\n\r\n### Module: `contifico`\r\n\r\nThe plugin registers a single module with three database models:\r\n\r\n#### `contifico_config` — Master configuration\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `api_key` | string | Contífico API key |\r\n| `api_pos` | string | Point-of-sale ID |\r\n| `bodega_ids` | string | Comma-separated warehouse IDs |\r\n| `sync_products_enabled` | boolean | Enable product sync |\r\n| `sync_customers_enabled` | boolean | Enable customer sync |\r\n| `auto_invoice_enabled` | boolean | Auto-create `FAC` on payment capture |\r\n| `auto_preinvoice_enabled` | boolean | Auto-create `PRE` on order placed |\r\n| `sync_interval_minutes` | number | Sync frequency (default: 60) |\r\n| `variant_mode` | enum | `\"auto\"` \\| `\"contifico\"` \\| `\"simple\"` \\| `\"weighted\"` |\r\n| `weighted_pvp_field` | enum | `\"pvp1\"` \\| `\"pvp2\"` \\| `\"pvp3\"` \\| `\"pvp4\"` |\r\n| `advanced_settings` | JSON | Versioned configuration (v2) |\r\n| `import_filters` | JSON | Product import filters |\r\n| `invoice_test_mode` | boolean | Test mode for invoicing |\r\n\r\n#### `contifico_entity_map` — Medusa ↔ Contífico ID mapping\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `entity_type` | enum | `product` \\| `variant` \\| `customer` \\| `category` \\| `invoice` |\r\n| `medusa_id` | string | Medusa entity ID (or typed key like `order_id:FAC`) |\r\n| `contifico_id` | string | Contífico entity ID |\r\n| `metadata` | JSON? | Extra mapping data |\r\n\r\n#### `contifico_sync_log` — Audit trail\r\n\r\n| Field | Type | Description |\r\n|-------|------|-------------|\r\n| `sync_type` | enum | `products` \\| `stock` \\| `customers` \\| `invoice` |\r\n| `status` | enum | `queued` \\| `running` \\| `success` \\| `partial` \\| `error` \\| `cancelled` |\r\n| `phase` | string? | Current phase description |\r\n| `progress_percent` | number? | Progress 0–100 |\r\n| `duration_ms` | number? | Total duration |\r\n| `total_processed` | number? | Items processed |\r\n| `total_errors` | number? | Error count |\r\n| `details` | JSON? | Detailed results |\r\n| `correlation_id` | string? | Correlation ID for tracing |\r\n\r\n---\r\n\r\n### HTTP Client\r\n\r\nThe plugin includes a purpose-built HTTP client with:\r\n\r\n- **Automatic retry** with exponential backoff\r\n- **Request timeout** (15s default)\r\n- **SSRF protection** — blocks private IP ranges\r\n\r\nSub-clients:\r\n\r\n| Client | Scope |\r\n|--------|-------|\r\n| `ContificoProductsClient` | Product & category CRUD |\r\n| `ContificoInvoicesClient` | Create, query, cancel documents |\r\n| `ContificoCustomersClient` | Search & create customers |\r\n| `ContificoInventoryClient` | Stock lookups |\r\n\r\n---\r\n\r\n### Weighted Pricing Strategies\r\n\r\nThe plugin supports pluggable pricing strategies for weight-based products:\r\n\r\n#### Built-in strategies\r\n\r\n| Strategy | Description |\r\n|----------|-------------|\r\n| `fixed_pvp_field` | Uses a fixed PVP field (`pvp1`–`pvp4`) for all products |\r\n| `rules_by_weight` | Calculates PVP based on weight range rules (e.g., 100–250g, 250–500g) |\r\n\r\n**Price resolution precedence:**\r\n\r\n1. Per-product override (`product.metadata.weighted_pvp_field`)\r\n2. Active weighted strategy\r\n3. Fallback field from strategy defaults\r\n\r\n#### Custom strategies\r\n\r\nStrategies implement the `WeightedPriceStrategy` interface:\r\n\r\n```typescript\r\ninterface WeightedPriceStrategy {\r\n  id: string\r\n  label: string\r\n  description: string\r\n  capabilities: {\r\n    uses_fixed_field?: boolean\r\n    uses_weight_rules?: boolean\r\n    supports_price_lock?: boolean\r\n  }\r\n  defaultConfig: object\r\n  normalizeConfig(config: unknown): object\r\n  validate(config: unknown): ValidationResult\r\n  resolvePriceField(product: any, context: any): string | number\r\n  explain(product: any, context: any): string\r\n}\r\n```\r\n\r\n---\r\n\r\n### Config Gates (UI Dependency Matrix)\r\n\r\nThe admin UI uses declarative dependency gates to show/hide/disable fields based on configuration state:\r\n\r\n| Gate | Visible When | Enabled When |\r\n|------|-------------|--------------|\r\n| `weighted_strategy` | `variant_mode === \"weighted\"` | always |\r\n| `weighted_price_lock` | sync_products enabled | strategy `supports_price_lock` |\r\n| `auto_invoice` | always | `api_pos` configured |\r\n| `sync_interval` | always | ≥ 1 automatic task active |\r\n\r\n---\r\n\r\n## API Reference\r\n\r\n### Admin Routes — Configuration\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/contifico/config` | Get current configuration |\r\n| `POST` | `/admin/contifico/config` | Create or update configuration |\r\n| `POST` | `/admin/contifico/config/check-connection` | Test API connection to Contífico |\r\n| `GET` | `/admin/contifico/config/bodegas` | List warehouses from Contífico |\r\n\r\n### Admin Routes — Sync\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `POST` | `/admin/contifico/sync/products` | Trigger product sync |\r\n| `POST` | `/admin/contifico/sync/products/preview` | Preview product sync (dry run) |\r\n| `POST` | `/admin/contifico/sync/products/stock` | Trigger stock sync |\r\n| `POST` | `/admin/contifico/sync/products/delete` | Delete imported products |\r\n| `POST` | `/admin/contifico/sync/products/delete/preview` | Preview product deletion (dry run) |\r\n| `POST` | `/admin/contifico/sync/customers` | Sync customers to Contífico |\r\n| `GET` | `/admin/contifico/sync-logs` | List recent sync logs |\r\n\r\n### Admin Routes — Products\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/contifico/products/linked` | List linked products (diagnostics) |\r\n| `GET` | `/admin/contifico/products/match` | Get product match recommendations |\r\n| `POST` | `/admin/contifico/products/link` | Create product link (Medusa ↔ Contífico) |\r\n| `PUT` | `/admin/contifico/products/link` | Re-link / update a product link |\r\n| `DELETE` | `/admin/contifico/products/link` | Remove a product link |\r\n| `POST` | `/admin/contifico/products/linked/migrate` | Migrate linked product metadata |\r\n\r\n### Admin Routes — Invoicing\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/contifico/invoices` | List invoices |\r\n| `POST` | `/admin/contifico/invoices` | Create invoice or run test actions |\r\n| `POST` | `/admin/contifico/invoices/preview` | Preview invoice document (dry run) |\r\n| `GET` | `/admin/orders/:id/contifico-documents` | Get document status for an order |\r\n| `POST` | `/admin/orders/:id/contifico-documents` | Create / update order documents |\r\n\r\n### Admin Routes — Media\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/contifico/media` | Proxy Contífico product images |\r\n\r\n### Health Check\r\n\r\n| Method | Endpoint | Description |\r\n|--------|----------|-------------|\r\n| `GET` | `/admin/plugin` | Plugin health check (admin) |\r\n| `GET` | `/store/plugin` | Plugin health check (store) |\r\n\r\n---\r\n\r\n## Subscribers (Automation)\r\n\r\n| Event | Action |\r\n|-------|--------|\r\n| `CONTIFICO_PRODUCTS_SYNC_REQUESTED` | Runs product sync job |\r\n| `CONTIFICO_PRODUCTS_STOCK_REQUESTED` | Runs stock sync job |\r\n| `order.placed` | Creates `PRE` (if `auto_preinvoice_enabled`) |\r\n| `payment.captured` | Creates `FAC` (if `auto_invoice_enabled` + `api_pos`) |\r\n\r\nAll automated operations use `correlation_id` for end-to-end tracing.\r\n\r\n---\r\n\r\n## Invoicing\r\n\r\n### Idempotency\r\n\r\nDocuments use typed keys (`order_id:PRE`, `order_id:FAC`) to prevent duplicates. The system performs:\r\n\r\n1. **Local deduplication** — checks `contifico_entity_map` before creating.\r\n2. **Remote deduplication** — queries Contífico API for existing documents.\r\n3. **Race condition handling** — if a remote duplicate is detected after creation, the local duplicate is cancelled defensively.\r\n\r\n### Test Mode\r\n\r\nWhen `invoice_test_mode` is enabled, documents are created with prefix `test:order_id:TYPE` and can be bulk-deleted via `deleteTestInvoiceDocuments()`.\r\n\r\n---\r\n\r\n## Testing\r\n\r\n```bash\r\npnpm test\r\n```\r\n\r\nThe plugin includes a Vitest suite covering:\r\n\r\n- Legacy → v2 config migration\r\n- Weighted strategy registry\r\n- Dependency gate evaluation\r\n- Product sync pipeline\r\n- PRE/FAC subscriber flows\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT — [CodeMind](https://codemind.ec)\r\n","readmeFilename":"README.md"}