{"_id":"@biobarica/seller-resolution","_rev":"2-686e0fb67553dbd7c38f38413f09d6e9","name":"@biobarica/seller-resolution","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@biobarica/seller-resolution","version":"1.0.0","keywords":["seller","pipedrive","firestore","biobarica"],"author":{"name":"BioBarica"},"license":"MIT","_id":"@biobarica/seller-resolution@1.0.0","maintainers":[{"name":"edumetz16","email":"eduardo.linead@gmail.com"}],"dist":{"shasum":"c8010f34deea34b205c099506bcfab4670bef358","tarball":"https://registry.npmjs.org/@biobarica/seller-resolution/-/seller-resolution-1.0.0.tgz","fileCount":34,"integrity":"sha512-fHox3yNn0eS9XwY0D6a0941sAHFJiq3V4Sf3198UJCocx/jyQeR6mnCf/8r/vCRBOSj3FdoMFh14FrwDHSPyEw==","signatures":[{"sig":"MEUCIQD0vahEpuR0/o4FgQYPBF5EWvIot7a434+3zjzBG2mE8gIgVnYkpT1UdzV6qwjGcBZiaLdm0sU4sZoS5Z2po1aYr2g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71596},"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","test:watch":"jest --watch","build:watch":"tsc --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"edumetz16","email":"eduardo.linead@gmail.com"},"_npmVersion":"11.6.2","description":"Resolves a seller from Firestore by phone number or country using Pipedrive","directories":{},"_nodeVersion":"25.0.0","dependencies":{"pipedrive":"^32.2.1","firebase-admin":">=11.0.0","libphonenumber-js":"^1.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","ts-jest":"^29.4.9","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^20.0.0"},"peerDependencies":{"firebase-admin":">=11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/seller-resolution_1.0.0_1777382826098_0.4554650611629685","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@biobarica/seller-resolution","version":"1.0.2","description":"Resolves a seller from Firestore by phone number or country using Pipedrive","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"scripts":{"build":"tsc","build:watch":"tsc --watch","test":"jest","test:watch":"jest --watch","lint":"eslint src --ext .ts","prepublishOnly":"npm run build"},"keywords":["seller","pipedrive","firestore","biobarica"],"author":{"name":"BioBarica"},"license":"MIT","dependencies":{"firebase-admin":">=11.0.0","libphonenumber-js":"^1.11.0","pipedrive":"^32.2.1"},"devDependencies":{"@types/jest":"^30.0.0","@types/node":"^20.0.0","jest":"^30.3.0","ts-jest":"^29.4.9","typescript":"^5.0.0"},"peerDependencies":{"firebase-admin":">=11.0.0"},"_id":"@biobarica/seller-resolution@1.0.2","gitHead":"7975eda64bd412866be322510e8c32facc045599","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Ky/VWUzw5gBtz16IXa50IBmNzOfJYh9OSN6rOsVXeOGq/7KeAEmErSIUg495Ilu3ZtfXF5C+cDKJOX5r+iQ0dw==","shasum":"d870965f09896422ad3557a0c13914ca25f138fa","tarball":"https://registry.npmjs.org/@biobarica/seller-resolution/-/seller-resolution-1.0.2.tgz","fileCount":34,"unpackedSize":79234,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCvMC6AbUItpP6HiIlkitaNlb+sX+FUQjUa2PnLx4Cm/AIgJpE7HetY+I0xVC/+UXmTeos3Ra2eEiXGGwZZfmEng/U="}]},"_npmUser":{"name":"edumetz16","email":"eduardo.linead@gmail.com"},"directories":{},"maintainers":[{"name":"edumetz16","email":"eduardo.linead@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/seller-resolution_1.0.2_1777396640792_0.30982316233468765"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-28T13:27:05.991Z","modified":"2026-04-28T17:17:21.141Z","1.0.0":"2026-04-28T13:27:06.302Z","1.0.2":"2026-04-28T17:17:21.025Z"},"author":{"name":"BioBarica"},"license":"MIT","keywords":["seller","pipedrive","firestore","biobarica"],"description":"Resolves a seller from Firestore by phone number or country using Pipedrive","maintainers":[{"name":"edumetz16","email":"eduardo.linead@gmail.com"}],"readme":"# @biobarica/seller-resolution\n\nResolves a Pipedrive seller for a given phone number or country code using Firestore as the seller registry.\n\n## How it works\n\n1. **By phone** — searches Pipedrive for an existing contact with that number. If one is found and already has an owner, that owner is returned. Otherwise the phone's country is extracted and the flow continues as below.\n2. **By country** — fetches all sellers from the `user_details` Firestore collection that are assigned to that country (or to the `\"ROW\"` catch-all), then picks one at random weighted by their configured country weights.\n\n## Installation\n\n```bash\nnpm install @biobarica/seller-resolution\n```\n\n## Usage\n\n### With a Firestore instance\n\nUse this when you already have `firebase-admin` initialised in your app.\n\n```typescript\nimport { SellersService, BusinessUnit } from \"@biobarica/seller-resolution\";\nimport { getFirestore } from \"firebase-admin/firestore\";\n\nconst service = new SellersService({\n  pipedriveApiKey: process.env.PIPEDRIVE_API_KEY,\n  businessUnit: BusinessUnit.OXY,\n  defaultSellerId: 42,\n  defaultUserId: \"fallback-uid\",\n  db: getFirestore(),\n});\n```\n\n### With a service account\n\nUse this when you don't have `firebase-admin` set up yet. The package initialises it internally.\n\n```typescript\nimport { SellersService, BusinessUnit } from \"@biobarica/seller-resolution\";\nimport serviceAccount from \"./service-account.json\";\n\nconst service = new SellersService({\n  pipedriveApiKey: process.env.PIPEDRIVE_API_KEY,\n  businessUnit: BusinessUnit.OXY,\n  defaultSellerId: 42,\n  defaultUserId: \"fallback-uid\",\n  serviceAccount,\n});\n```\n\n> `db` and `serviceAccount` are mutually exclusive — TypeScript will report an error if you pass both.\n\n## API\n\n### `new SellersService(options, logger?)`\n\n| Option | Type | Required | Description |\n|---|---|---|---|\n| `pipedriveApiKey` | `string` | Yes | Pipedrive API key |\n| `businessUnit` | `string` | Yes | Business unit key used to scope seller selection (e.g. `\"oxy\"`) |\n| `db` | `Firestore` | One of | An existing Firestore instance |\n| `serviceAccount` | `ServiceAccountCredentials` | One of | Firebase service account credentials object |\n| `defaultSellerId` | `number` | No | Fallback Pipedrive seller id when no seller can be resolved |\n| `defaultUserId` | `string` | No | Fallback Firestore user id when no seller can be resolved |\n\nAn optional second argument accepts a custom `Logger` (`{ info, warn, error }`). Defaults to `console`.\n\n### `getSeller(phoneNumber)`\n\nResolves a seller for a phone number. Accepts E.164 format (`+5491123456789`) or without the leading `+`.\n\n```typescript\nconst result = await service.getSeller(\"+5491123456789\");\n// result.sellerId                   — Pipedrive seller id (number | undefined)\n// result.userId                     — Firestore user document id (string | undefined)\n// result.displayName                — seller display name (string | undefined)\n// result.calendarLink               — booking calendar URL (string | undefined)\n// result.discoveryCallCalendarLink  — discovery call calendar URL (string | undefined)\n// result.whatsappNumber             — WhatsApp contact number (string | undefined)\n```\n\n### `getSellerByCountry(countryCode)`\n\nResolves a seller directly from a country code, skipping the Pipedrive lookup.\n\n```typescript\nconst { sellerId, userId, displayName, calendarLink } = await service.getSellerByCountry(\"AR\");\n```\n\n## Firestore data model\n\nThe service reads from the `user_details` collection. Each seller document must have at least:\n\n```jsonc\n{\n  \"id\": \"firestore-doc-id\",\n  \"roles\": [\"seller\"],\n  \"sellerInfo\": {\n    \"pipedriveSellerId\": 42,\n    \"assignedCountries\": [\"AR\", \"CL\"],   // ISO 3166-1 alpha-2 or \"ROW\" as catch-all\n    \"countryWeights\": { \"AR\": 0.7, \"CL\": 0.3 },\n    \"businessUnits\": [\"oxy\"]             // omit to make available to all business units\n  }\n}\n```\n\n### Per-business-unit overrides\n\nA seller can override `assignedCountries` and `countryWeights` for a specific business unit by nesting them under the business unit key:\n\n```jsonc\n{\n  \"sellerInfo\": {\n    \"pipedriveSellerId\": 42,\n    \"assignedCountries\": [\"ROW\"],\n    \"oxy\": {\n      \"assignedCountries\": [\"AR\", \"BR\"],\n      \"countryWeights\": { \"AR\": 0.6, \"BR\": 0.4 }\n    }\n  }\n}\n```\n\n### Country weights\n\nWeights do not need to sum to 1 — the selection is proportional. A seller with weight `2` is twice as likely to be picked as one with weight `1`. If no weight is configured for a country, all eligible sellers share equal probability.\n\n## Custom logger\n\n```typescript\nimport { SellersService, Logger } from \"@biobarica/seller-resolution\";\n\nconst logger: Logger = {\n  info: (msg) => myLogger.info(msg),\n  warn: (msg) => myLogger.warn(msg),\n  error: (msg) => myLogger.error(msg),\n};\n\nconst service = new SellersService({ ... }, logger);\n```\n","readmeFilename":"README.md"}