Title: Opportunities (CRM Deals) Description: Sales opportunities with pipeline stages, amounts and contact linking — part of the CRM pack --- The Opportunity type represents a sales deal — a potential revenue object that moves through a pipeline. Without opportunities a CRM is just a contact database; with them it tracks the actual sales process. Opportunities ship as part of the CRM pack (crm-pack) alongside Contacts and Emails. They can be installed standalone via the Opportunities module if you only need the deal pipeline without the rest of the CRM. When to use Tracking sales deals through stages from lead to closed-won/closed-lost Linking revenue forecasts to specific contacts and companies Reporting on pipeline value, win rates and expected close dates Schema The schema lives in packages/shared/src/typesystem/types/opportunity.ts and is registered as the schema extension opportunities:v1 in packages/shared/src/typesystem/schema-extensions.ts. | Property | Type | Required | Description | | ------------------- | ------ | -------- | ------------------------------------------------------------------------------------- | | name | string | yes | Short, human-readable name of the deal | | amount | number | no | Expected revenue amount | | currency | string | no | ISO 4217 currency code: EUR (default), USD, GBP, CHF | | stage | enum | yes | One of lead, qualified, proposal, negotiation, won, lost (default lead) | | probability | number | no | Probability of closing the deal, expressed as a percentage (0–100) | | expectedCloseDate | number | no | Expected close date as a Unix timestamp in milliseconds | | company | string | no | Free-text company name (autocomplete-enabled) | | notes | string | no | Free-form notes | name and stage are the only required fields. The default stage is lead and the default currency is EUR. Pipeline stages The default pipeline ships with six stages: | Value | German | English | | ------------- | ------------ | ----------- | | lead | Lead | Lead | | qualified | Qualifiziert | Qualified | | proposal | Angebot | Proposal | | negotiation | Verhandlung | Negotiation | | won | Gewonnen | Won | | lost | Verloren | Lost | Stages are stored as a configurable enum on the type. Once the type is created in a project the project owner can customise the list via the regular type-editor flow. Relations When the Opportunity type is installed alongside a Contact type from the same install batch, the install process wires them up automatically (see packages/shared/src/templates/extensions/opportunity.type.ts): linksConfiguration is enabled, so emails, notes, calendar events and tasks can be linked to an Opportunity through the standard relations system — not only to a Contact. Backoffice page Installing the Opportunities BOM extension adds a navigation entry at /opportunities with a data view showing the columns: name, company, stage, amount, probability, expectedCloseDate The page uses the standard widget framework and inherits the same filtering, sorting and bulk-action behaviour as other backoffice modules. Installation The Opportunity module is available in the store as a standalone module and is pre-selected in the CRM pack: // packages/shared/src/templates/store.collections.ts modules: [FeatureName.CONTACT, FeatureName.OPPORTUNITY, FeatureName.EMAIL] | Identifier | Purpose | | ----------------------------------------- | --------------------------------------------- | | FeatureName.OPPORTUNITY | Opportunities module | | FeatureExtensionName.OPPORTUNITIES_TYPE | Creates the Opportunity data type | | FeatureExtensionName.OPPORTUNITIES_BOM | Adds the /opportunities navigation page | | FeatureRef.OPPORTUNITIES_TYPE | Reference for the created type entity | | FeatureRef.OPPORTUNITIES_BOM | Reference for the created BOM compound widget | | FeatureRef.OPPORTUNITIESBOMNAV_ENTRY | Reference for the created navigation entry | Existing CRM projects can install the new module from the store at any time — no migration is required because the type and BOM are created on demand by the store install flow rather than baked into existing tenant data. Duplicate detection Duplicate detection is enabled with a 0.85 threshold against the name and company fields. Two deals named "Q4 Renewal" for the same company are flagged as likely duplicates at import or creation time.