Dataverse
Legacy (read-only, narrow scope) — Dataverse (PowerCRM on Microsoft Dynamics 365) was RENEWA’s previous CRM. HubSpot Integration is the primary CRM today (Deal = Project). The Dataverse client remains live only for two read paths: bootstrapping document-obtaining collections from a PowerCRM project URL, and feeding PDF form data fields. There is no bi-directional sync and no building/project/contact import pipeline.
Architecture
| Component | Path |
|---|---|
| API client | backend/src/lib/dataverse-client.ts (Power Apps URL parsing, OAuth client-credentials, project data retrieval) |
| Collection bootstrap | backend/src/services/collection-service.ts (createFromCrm, sanitization via sanitizeDataverseData) |
| PDF export | backend/src/services/pdf-export-service.ts (Dataverse field schemas + project data for filled PDFs) |
| Import tracking (historical) | dataverse_imports table — still in schema.ts, no runtime writers remain |
Live Usage
- Document-obtaining collections from a CRM URL: an operator pastes a PowerCRM project URL (
crmUrl) into the collection creation wizard (frontend/src/components/document-obtaining/CreateCollectionWizard.tsx). The backend parses the URL (parseDataverseUrl), fetches project, customer (contact or account) and representation data from the Dataverse Web API, sanitizes it, and pre-fills the collection. Responses are cached in Redis (CACHE_KEYS.dataverseProject) for reuse. - PDF data fields: the admin PDF template builder can map form fields to Dataverse field schemas per environment (“Browse Dataverse Fields” in the admin UI);
pdf-export-service.tsfetches schemas and project data to generate filled PDFs.
Configuration
| Secret | Purpose |
|---|---|
DATAVERSE_API_URL | Dataverse Web API endpoint |
DATAVERSE_CLIENT_ID / DATAVERSE_CLIENT_SECRET | OAuth 2.0 client-credentials flow |
DATAVERSE_TENANT_ID | Azure tenant |
Secrets live in Infisical (EU). The CRM-URL flows fail with a clear error when credentials are not configured (requireDataverseCredentials).
Polymorphic Lookup Quirks
Dataverse navigation properties are inconsistent: polymorphic lookups (PropertyOwner, InvoiceReceivingEntity) use the _shadow_contact / _shadow_account suffix, while non-polymorphic lookups (Representation) use just _shadow (e.g. pragdev_RepresentationId_shadow).
Historical Notes
- “Dataverse-era” collections predate the HubSpot model and lack a
quoteId; entity resolution for them converges on the project (see I#1802 discussion). - The earlier description of a full import pipeline (buildings/projects/contacts/companies into R1 tables, triggered from the Admin Dashboard and logged to
dataverse_imports) no longer matches the code:dataverse_importshas no runtime writers, and CRM entity mirroring is HubSpot’s job. - The legacy JIRA seed import (
db/seeds/scripts/jira-import.ts) no longer exists — theseeds/directory was retired in favour ofbackend/src/db/mocks/.
Related
- HubSpot Integration — the primary CRM integration
- Document Obtaining — collection bootstrap from CRM URLs
- PDF Templates — Dataverse-backed data fields
- External Integrations — All third-party integrations