import { SmrtObject } from '@happyvertical/smrt-core'; import { OpportunityOptions, OpportunityStatus } from '../types.js'; /** * Opportunity is a qualified engagement: a deal with an expected value moving * through the stages of a PipelineDefinition. * * Money is integer cents (`expectedValueCents`, INTEGER) with an ISO 4217 * `currency`; `probability` is a decimal in `0`–`1` (DECIMAL). Stage * movement goes through `OpportunityCollection.moveToStage()`, which * validates the stage belongs to the opportunity's pipeline, adopts the * stage's probability, closes the deal on terminal stages, and writes a * `stage_change` SalesActivity. `sourceKind`/`sourceId` are copied from the * originating Lead at qualification time so reporting can attribute won * revenue without joining back through leads. * * @example * ```typescript * const opportunities = await OpportunityCollection.create({ db }); * const moved = await opportunities.moveToStage({ * opportunityId: opportunity.id ?? '', * stageId: proposalStage.id ?? '', * }); * ``` */ export declare class Opportunity extends SmrtObject { /** * Tenant ID for multi-tenant isolation. * Nullable to support both tenant-scoped and global opportunities. */ tenantId: string | null; /** Deal name shown on boards and lists. Required. */ name: string; /** Originating lead (empty for opportunities created directly). */ leadId: string; /** Owning sales rep. */ ownerRepId: string; /** Pipeline the deal moves through. */ pipelineId: string; /** Current stage within the pipeline. */ stageId: string; /** Expected deal value in integer cents (INTEGER column). */ expectedValueCents: number; /** ISO 4217 currency code for `expectedValueCents`. */ currency: string; /** * Win probability (`0`–`1`, DECIMAL). Adopted from the current stage's * default on stage moves unless explicitly overridden. */ probability: number; /** Forecasted close date. */ expectedCloseAt: Date | null; /** Lifecycle status; `open → won|lost` is save-guarded, terminal after. */ status: OpportunityStatus; /** * Human-readable outcome note — conventionally the loss reason * (`'budget cut'`) or a win annotation. */ outcomeReason: string; /** When the deal closed as won. */ wonAt: Date | null; /** When the deal closed as lost. */ lostAt: Date | null; /** * Acquisition source copied from the originating lead at qualification * time (open string), kept denormalized for reporting. */ sourceKind: string; /** Identifier within the `sourceKind` namespace (copied from the lead). */ sourceId: string; /** * Free-form JSON object stored as a string. Use * {@link getMetadata}/{@link setMetadata} instead of parsing manually. */ metadata: string; constructor(options?: OpportunityOptions); /** Whether the deal is still in play. */ isOpen(): boolean; /** Whether the deal closed (won or lost). */ isClosed(): boolean; /** Parse the metadata JSON string; returns `{}` on malformed content. */ getMetadata(): Record; /** Serialize and store the metadata object. */ setMetadata(metadata: Record): void; /** * Capture the status the row was loaded with so the save-time transition * guard can reject illegal status flips made via raw field assignment. * Only persisted rows carry a prior status. */ initialize(): Promise; /** * Validate the status transition before persisting, then save. A forged * `status` (e.g. re-opening a lost deal) is rejected here regardless of * how the instance was constructed. */ save(): Promise; /** * Reject an illegal status flip done via raw assignment. No-op transitions * and brand-new rows are always allowed. */ protected assertOpportunityStatusTransition(prior: OpportunityStatus | undefined): void; /** * Resolve the AUTHORITATIVE prior status (commerce Contract pattern): when * this instance carries an `id`, re-read the persisted row and use its * `status` as the prior — a create-onto-existing is an update, and an * un-hydrated instance must not bypass the guard. Falls back to the * load-time WeakMap (empty for truly new rows → `undefined` = new). */ protected resolvePriorStatus(): Promise; } export default Opportunity; //# sourceMappingURL=Opportunity.d.ts.map