127 lines
6.2 KiB
TypeScript
127 lines
6.2 KiB
TypeScript
import {
|
||
ACCOUNT_SIDES,
|
||
AFFILIATION_KINDS,
|
||
CUSTOMER_SEGMENTS,
|
||
DEMAND_STAGES,
|
||
INTERCONNECT_TYPES,
|
||
PRODUCT_LINES,
|
||
SUPPLIER_TYPES,
|
||
SUPPLY_STAGES,
|
||
} from './ontology';
|
||
|
||
export const IMPORT_ENTITIES = ['account', 'contact', 'demand_deal', 'supply_deal'] as const;
|
||
export type ImportEntity = (typeof IMPORT_ENTITIES)[number];
|
||
|
||
export type ImportFieldKind =
|
||
| 'text'
|
||
| 'email'
|
||
| 'url'
|
||
| 'uuid'
|
||
| 'integer'
|
||
| 'decimal'
|
||
| 'boolean'
|
||
| 'date'
|
||
| 'currency'
|
||
| 'enum';
|
||
|
||
export interface ImportFieldDefinition {
|
||
key: string;
|
||
label: string;
|
||
kind: ImportFieldKind;
|
||
required?: boolean;
|
||
options?: readonly string[];
|
||
min?: number;
|
||
max?: number;
|
||
maxLength?: number;
|
||
description?: string;
|
||
/** False for non-null columns where a blank update must leave the stored value intact. */
|
||
clearable?: boolean;
|
||
}
|
||
|
||
export interface ImportEntityDefinition {
|
||
label: string;
|
||
description: string;
|
||
fields: readonly ImportFieldDefinition[];
|
||
}
|
||
|
||
export const IMPORT_ENTITY_DEFINITIONS: Readonly<Record<ImportEntity, ImportEntityDefinition>> = {
|
||
account: {
|
||
label: 'Accounts',
|
||
description: 'Customer, supplier, and dual-sided organisations.',
|
||
fields: [
|
||
{ key: 'name', label: 'Account name', kind: 'text', required: true, maxLength: 200 },
|
||
{ key: 'domain', label: 'Domain', kind: 'text', maxLength: 255 },
|
||
{ key: 'website', label: 'Website', kind: 'url' },
|
||
{ key: 'description', label: 'Description', kind: 'text', maxLength: 10_000 },
|
||
{ key: 'side', label: 'Commercial side', kind: 'enum', required: true, options: ACCOUNT_SIDES },
|
||
{ key: 'supplierType', label: 'Supplier type', kind: 'enum', options: SUPPLIER_TYPES },
|
||
{ key: 'customerSegment', label: 'Customer segment', kind: 'enum', options: CUSTOMER_SEGMENTS },
|
||
{ key: 'country', label: 'Country', kind: 'text', maxLength: 160 },
|
||
{ key: 'region', label: 'Region', kind: 'text', maxLength: 160 },
|
||
{ key: 'jurisdiction', label: 'Legal jurisdiction', kind: 'text', maxLength: 160 },
|
||
{ key: 'ultimateParentName', label: 'Ultimate parent', kind: 'text', maxLength: 200 },
|
||
{ key: 'ultimateParentCountry', label: 'Ultimate parent country', kind: 'text', maxLength: 160 },
|
||
],
|
||
},
|
||
contact: {
|
||
label: 'Contacts',
|
||
description: 'People and their evidenced relationship to an account.',
|
||
fields: [
|
||
{ key: 'accountId', label: 'Account ID', kind: 'uuid', description: 'A PIG account UUID, not an account name.' },
|
||
{ key: 'fullName', label: 'Full name', kind: 'text', required: true, maxLength: 200 },
|
||
{ key: 'firstName', label: 'First name', kind: 'text', maxLength: 100 },
|
||
{ key: 'lastName', label: 'Last name', kind: 'text', maxLength: 100 },
|
||
{ key: 'title', label: 'Title', kind: 'text', maxLength: 200 },
|
||
{ key: 'email', label: 'Email', kind: 'email', description: 'Import only sourced or provided addresses.' },
|
||
{ key: 'phone', label: 'Phone', kind: 'text', maxLength: 100 },
|
||
{ key: 'linkedinUrl', label: 'LinkedIn URL', kind: 'url' },
|
||
{ key: 'twitterHandle', label: 'X / Twitter handle', kind: 'text', maxLength: 100 },
|
||
{ key: 'githubHandle', label: 'GitHub handle', kind: 'text', maxLength: 100 },
|
||
{ key: 'websiteUrl', label: 'Website URL', kind: 'url' },
|
||
{ key: 'affiliation', label: 'Affiliation', kind: 'enum', options: AFFILIATION_KINDS, clearable: false },
|
||
{ key: 'isDecisionMaker', label: 'Decision maker', kind: 'boolean', clearable: false },
|
||
{ key: 'confidenceNote', label: 'Provenance note', kind: 'text', maxLength: 2_000 },
|
||
],
|
||
},
|
||
demand_deal: {
|
||
label: 'Demand deals',
|
||
description: 'Customer opportunities. Account relationships must already exist in PIG.',
|
||
fields: [
|
||
{ key: 'accountId', label: 'Account ID', kind: 'uuid', required: true },
|
||
{ key: 'name', label: 'Deal name', kind: 'text', required: true, maxLength: 200 },
|
||
{ key: 'description', label: 'Description', kind: 'text', maxLength: 10_000 },
|
||
{ key: 'productLine', label: 'Product line', kind: 'enum', required: true, options: PRODUCT_LINES },
|
||
{ key: 'stage', label: 'Stage', kind: 'enum', required: true, options: DEMAND_STAGES },
|
||
{ key: 'acvCents', label: 'ACV in cents', kind: 'integer', min: 0 },
|
||
{ key: 'tcvCents', label: 'TCV in cents', kind: 'integer', min: 0 },
|
||
{ key: 'currency', label: 'Currency', kind: 'currency', clearable: false },
|
||
{ key: 'termMonths', label: 'Term months', kind: 'integer', min: 1 },
|
||
{ key: 'probability', label: 'Probability (0–1)', kind: 'decimal', min: 0, max: 1 },
|
||
{ key: 'expectedCloseDate', label: 'Expected close date', kind: 'date' },
|
||
{ key: 'msaExecuted', label: 'MSA executed', kind: 'boolean', clearable: false },
|
||
{ key: 'dpaExecuted', label: 'DPA executed', kind: 'boolean', clearable: false },
|
||
{ key: 'closedReason', label: 'Closed reason', kind: 'text', maxLength: 2_000 },
|
||
],
|
||
},
|
||
supply_deal: {
|
||
label: 'Supply deals',
|
||
description: 'Capacity sourcing opportunities attached to supplier accounts.',
|
||
fields: [
|
||
{ key: 'accountId', label: 'Account ID', kind: 'uuid', required: true },
|
||
{ key: 'name', label: 'Deal name', kind: 'text', required: true, maxLength: 200 },
|
||
{ key: 'stage', label: 'Stage', kind: 'enum', required: true, options: SUPPLY_STAGES },
|
||
{ key: 'gpuType', label: 'GPU type', kind: 'text', maxLength: 100 },
|
||
{ key: 'gpuCount', label: 'GPU count', kind: 'integer', min: 1 },
|
||
{ key: 'interconnectType', label: 'Interconnect', kind: 'enum', options: INTERCONNECT_TYPES },
|
||
{ key: 'targetCostPerGpuHourCents', label: 'Target cost in cents', kind: 'integer', min: 0 },
|
||
{ key: 'termMonths', label: 'Term months', kind: 'integer', min: 1 },
|
||
{ key: 'availableFrom', label: 'Available from', kind: 'date' },
|
||
{ key: 'technicalVerdict', label: 'Technical verdict', kind: 'text', maxLength: 1_000 },
|
||
{ key: 'technicalNotes', label: 'Technical notes', kind: 'text', maxLength: 10_000 },
|
||
{ key: 'financialVerdict', label: 'Financial verdict', kind: 'text', maxLength: 1_000 },
|
||
{ key: 'financialNotes', label: 'Financial notes', kind: 'text', maxLength: 10_000 },
|
||
{ key: 'rejectionReason', label: 'Rejection reason', kind: 'text', maxLength: 2_000 },
|
||
],
|
||
},
|
||
};
|