@nextsparkjs/theme-crm 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CRM_PLAN.md +343 -0
  2. package/about.md +122 -0
  3. package/config/app.config.ts +185 -0
  4. package/config/billing.config.ts +187 -0
  5. package/config/dashboard.config.ts +372 -0
  6. package/config/dev.config.ts +55 -0
  7. package/config/features.config.ts +336 -0
  8. package/config/flows.config.ts +511 -0
  9. package/config/permissions.config.ts +297 -0
  10. package/config/theme.config.ts +111 -0
  11. package/entities/activities/activities.config.ts +61 -0
  12. package/entities/activities/activities.fields.ts +362 -0
  13. package/entities/activities/activities.service.ts +503 -0
  14. package/entities/activities/activities.types.ts +117 -0
  15. package/entities/activities/messages/en.json +123 -0
  16. package/entities/activities/messages/es.json +123 -0
  17. package/entities/activities/migrations/020_activities_table.sql +123 -0
  18. package/entities/activities/migrations/021_activities_metas.sql +114 -0
  19. package/entities/activities/migrations/022_activities_sample_data.sql +420 -0
  20. package/entities/campaigns/campaigns.config.ts +61 -0
  21. package/entities/campaigns/campaigns.fields.ts +413 -0
  22. package/entities/campaigns/campaigns.service.ts +426 -0
  23. package/entities/campaigns/campaigns.types.ts +124 -0
  24. package/entities/campaigns/messages/en.json +145 -0
  25. package/entities/campaigns/messages/es.json +145 -0
  26. package/entities/campaigns/migrations/001_campaigns_table.sql +127 -0
  27. package/entities/campaigns/migrations/002_campaigns_metas.sql +114 -0
  28. package/entities/campaigns/migrations/003_campaigns_sample_data.sql +364 -0
  29. package/entities/companies/companies.config.ts +61 -0
  30. package/entities/companies/companies.fields.ts +429 -0
  31. package/entities/companies/companies.service.ts +566 -0
  32. package/entities/companies/companies.types.ts +125 -0
  33. package/entities/companies/messages/en.json +146 -0
  34. package/entities/companies/messages/es.json +146 -0
  35. package/entities/companies/migrations/001_companies_table.sql +150 -0
  36. package/entities/companies/migrations/002_companies_metas.sql +114 -0
  37. package/entities/companies/migrations/003_companies_sample_data.sql +246 -0
  38. package/entities/contacts/contacts.config.ts +61 -0
  39. package/entities/contacts/contacts.fields.ts +359 -0
  40. package/entities/contacts/contacts.service.ts +509 -0
  41. package/entities/contacts/contacts.types.ts +108 -0
  42. package/entities/contacts/messages/en.json +117 -0
  43. package/entities/contacts/messages/es.json +117 -0
  44. package/entities/contacts/migrations/001_contacts_table.sql +134 -0
  45. package/entities/contacts/migrations/002_contacts_metas.sql +114 -0
  46. package/entities/contacts/migrations/003_contacts_sample_data.sql +421 -0
  47. package/entities/leads/leads.config.ts +61 -0
  48. package/entities/leads/leads.fields.ts +336 -0
  49. package/entities/leads/leads.service.ts +496 -0
  50. package/entities/leads/leads.types.ts +114 -0
  51. package/entities/leads/messages/en.json +132 -0
  52. package/entities/leads/messages/es.json +132 -0
  53. package/entities/leads/migrations/001_leads_table.sql +150 -0
  54. package/entities/leads/migrations/002_leads_metas.sql +120 -0
  55. package/entities/leads/migrations/003_leads_sample_data.sql +242 -0
  56. package/entities/notes/messages/en.json +114 -0
  57. package/entities/notes/messages/es.json +114 -0
  58. package/entities/notes/migrations/020_notes_table.sql +118 -0
  59. package/entities/notes/migrations/021_notes_metas.sql +114 -0
  60. package/entities/notes/migrations/022_notes_sample_data.sql +275 -0
  61. package/entities/notes/notes.config.ts +61 -0
  62. package/entities/notes/notes.fields.ts +283 -0
  63. package/entities/notes/notes.service.ts +320 -0
  64. package/entities/notes/notes.types.ts +102 -0
  65. package/entities/opportunities/messages/en.json +107 -0
  66. package/entities/opportunities/messages/es.json +107 -0
  67. package/entities/opportunities/migrations/010_opportunities_table.sql +145 -0
  68. package/entities/opportunities/migrations/011_opportunities_metas.sql +114 -0
  69. package/entities/opportunities/migrations/012_opportunities_sample_data.sql +438 -0
  70. package/entities/opportunities/opportunities.config.ts +61 -0
  71. package/entities/opportunities/opportunities.fields.ts +416 -0
  72. package/entities/opportunities/opportunities.service.ts +525 -0
  73. package/entities/opportunities/opportunities.types.ts +135 -0
  74. package/entities/pipelines/messages/en.json +115 -0
  75. package/entities/pipelines/messages/es.json +115 -0
  76. package/entities/pipelines/migrations/001_pipelines_table.sql +106 -0
  77. package/entities/pipelines/migrations/002_pipelines_metas.sql +114 -0
  78. package/entities/pipelines/migrations/003_pipelines_sample_data.sql +91 -0
  79. package/entities/pipelines/pipelines.config.ts +62 -0
  80. package/entities/pipelines/pipelines.fields.ts +193 -0
  81. package/entities/pipelines/pipelines.service.ts +383 -0
  82. package/entities/pipelines/pipelines.types.ts +78 -0
  83. package/entities/products/messages/en.json +135 -0
  84. package/entities/products/messages/es.json +135 -0
  85. package/entities/products/migrations/001_products_table.sql +117 -0
  86. package/entities/products/migrations/002_products_metas.sql +114 -0
  87. package/entities/products/migrations/003_products_sample_data.sql +247 -0
  88. package/entities/products/products.config.ts +62 -0
  89. package/entities/products/products.fields.ts +361 -0
  90. package/entities/products/products.service.ts +437 -0
  91. package/entities/products/products.types.ts +125 -0
  92. package/lib/crm-constants.ts +77 -0
  93. package/lib/crm-utils.ts +185 -0
  94. package/lib/selectors.ts +333 -0
  95. package/messages/en.json +131 -0
  96. package/messages/es.json +131 -0
  97. package/migrations/999_theme_sample_data.sql +473 -0
  98. package/package.json +18 -0
  99. package/pendings.md +205 -0
  100. package/permissions-matrix.md +216 -0
  101. package/styles/components.css +414 -0
  102. package/styles/crm-theme.css +358 -0
  103. package/styles/globals.css +576 -0
  104. package/styles/variables.css +111 -0
  105. package/templates/dashboard/(main)/activities/components/ActivityCard.tsx +169 -0
  106. package/templates/dashboard/(main)/activities/components/ActivityTimeline.tsx +165 -0
  107. package/templates/dashboard/(main)/activities/page.tsx +297 -0
  108. package/templates/dashboard/(main)/campaigns/page.tsx +373 -0
  109. package/templates/dashboard/(main)/companies/page.tsx +296 -0
  110. package/templates/dashboard/(main)/contacts/page.tsx +347 -0
  111. package/templates/dashboard/(main)/layout.tsx +98 -0
  112. package/templates/dashboard/(main)/leads/page.tsx +335 -0
  113. package/templates/dashboard/(main)/opportunities/[id]/edit/page.tsx +95 -0
  114. package/templates/dashboard/(main)/opportunities/create/page.tsx +94 -0
  115. package/templates/dashboard/(main)/opportunities/page.tsx +350 -0
  116. package/templates/dashboard/(main)/pipelines/[id]/edit/page.tsx +95 -0
  117. package/templates/dashboard/(main)/pipelines/[id]/page.tsx +143 -0
  118. package/templates/dashboard/(main)/pipelines/create/page.tsx +94 -0
  119. package/templates/dashboard/(main)/pipelines/page.tsx +234 -0
  120. package/templates/dashboard/(main)/products/[id]/edit/page.tsx +97 -0
  121. package/templates/dashboard/(main)/products/[id]/page.tsx +509 -0
  122. package/templates/dashboard/(main)/products/create/page.tsx +96 -0
  123. package/templates/dashboard/(main)/products/page.tsx +308 -0
  124. package/templates/shared/ActionButtons.tsx +41 -0
  125. package/templates/shared/CRMDashboard.tsx +519 -0
  126. package/templates/shared/CRMDataTable.tsx +441 -0
  127. package/templates/shared/CRMMetricCard.tsx +76 -0
  128. package/templates/shared/CRMMobileNav.tsx +172 -0
  129. package/templates/shared/CRMSidebar.tsx +346 -0
  130. package/templates/shared/CRMTopBar.tsx +265 -0
  131. package/templates/shared/DealCard.tsx +123 -0
  132. package/templates/shared/EntityCard.tsx +58 -0
  133. package/templates/shared/OpportunityForm.tsx +649 -0
  134. package/templates/shared/PipelineForm.tsx +367 -0
  135. package/templates/shared/PipelineKanban.tsx +194 -0
  136. package/templates/shared/QuickFilters.tsx +47 -0
  137. package/templates/shared/StageColumn.tsx +175 -0
  138. package/templates/shared/StageSelect.tsx +177 -0
  139. package/templates/shared/StagesRepeater.tsx +317 -0
  140. package/templates/shared/index.ts +9 -0
@@ -0,0 +1,145 @@
1
+ -- ============================================================================
2
+ -- Opportunities Table Migration
3
+ -- CRM theme: Sales opportunities in the pipeline
4
+ -- Updated with team support and RLS
5
+ -- ============================================================================
6
+
7
+ -- ============================================
8
+ -- ENUM TYPES
9
+ -- ============================================
10
+ DO $$ BEGIN
11
+ CREATE TYPE opportunity_type AS ENUM ('new_business', 'existing_business', 'renewal');
12
+ EXCEPTION
13
+ WHEN duplicate_object THEN null;
14
+ END $$;
15
+
16
+ DO $$ BEGIN
17
+ CREATE TYPE opportunity_status AS ENUM ('open', 'won', 'lost');
18
+ EXCEPTION
19
+ WHEN duplicate_object THEN null;
20
+ END $$;
21
+
22
+ -- ============================================
23
+ -- TABLE
24
+ -- ============================================
25
+ CREATE TABLE IF NOT EXISTS "opportunities" (
26
+ "id" TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
27
+
28
+ -- Opportunity info
29
+ "name" VARCHAR(255) NOT NULL,
30
+ "companyId" TEXT REFERENCES "companies"("id") ON DELETE SET NULL,
31
+ "contactId" TEXT REFERENCES "contacts"("id") ON DELETE SET NULL,
32
+
33
+ -- Pipeline
34
+ "pipelineId" UUID, -- Reference to pipelines table
35
+ "stageId" VARCHAR(100),
36
+
37
+ -- Financials
38
+ "amount" DECIMAL(15,2) DEFAULT 0,
39
+ "currency" VARCHAR(3) DEFAULT 'USD',
40
+ "probability" INTEGER DEFAULT 0 CHECK ("probability" >= 0 AND "probability" <= 100),
41
+ "expectedRevenue" DECIMAL(15,2) GENERATED ALWAYS AS ("amount" * ("probability"::DECIMAL / 100)) STORED,
42
+
43
+ -- Dates
44
+ "closeDate" DATE,
45
+ "wonDate" DATE,
46
+ "lostDate" DATE,
47
+
48
+ -- Classification
49
+ "type" opportunity_type DEFAULT 'new_business',
50
+ "source" VARCHAR(100),
51
+ "competitor" VARCHAR(255),
52
+ "status" opportunity_status DEFAULT 'open',
53
+ "lostReason" TEXT,
54
+
55
+ -- Assignment
56
+ "assignedTo" TEXT REFERENCES "users"("id") ON DELETE SET NULL,
57
+
58
+ -- Ownership
59
+ "userId" TEXT NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
60
+ "teamId" TEXT NOT NULL REFERENCES "teams"("id") ON DELETE CASCADE,
61
+
62
+ -- Timestamps
63
+ "createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
64
+ "updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW()
65
+ );
66
+
67
+ -- ============================================
68
+ -- INDEXES
69
+ -- ============================================
70
+ CREATE INDEX IF NOT EXISTS "opportunities_teamId_idx" ON "opportunities" ("teamId");
71
+ CREATE INDEX IF NOT EXISTS "opportunities_userId_idx" ON "opportunities" ("userId");
72
+ CREATE INDEX IF NOT EXISTS "opportunities_companyId_idx" ON "opportunities" ("companyId");
73
+ CREATE INDEX IF NOT EXISTS "opportunities_contactId_idx" ON "opportunities" ("contactId");
74
+ CREATE INDEX IF NOT EXISTS "opportunities_pipelineId_idx" ON "opportunities" ("pipelineId");
75
+ CREATE INDEX IF NOT EXISTS "opportunities_status_idx" ON "opportunities" ("status");
76
+ CREATE INDEX IF NOT EXISTS "opportunities_closeDate_idx" ON "opportunities" ("closeDate");
77
+ CREATE INDEX IF NOT EXISTS "opportunities_assignedTo_idx" ON "opportunities" ("assignedTo");
78
+ CREATE INDEX IF NOT EXISTS "opportunities_amount_idx" ON "opportunities" ("amount" DESC);
79
+ CREATE INDEX IF NOT EXISTS "opportunities_createdAt_idx" ON "opportunities" ("createdAt" DESC);
80
+
81
+ -- ============================================
82
+ -- RLS
83
+ -- ============================================
84
+ ALTER TABLE "opportunities" ENABLE ROW LEVEL SECURITY;
85
+
86
+ -- Drop existing policies
87
+ DROP POLICY IF EXISTS "opportunities_select_policy" ON "opportunities";
88
+ DROP POLICY IF EXISTS "opportunities_insert_policy" ON "opportunities";
89
+ DROP POLICY IF EXISTS "opportunities_update_policy" ON "opportunities";
90
+ DROP POLICY IF EXISTS "opportunities_delete_policy" ON "opportunities";
91
+
92
+ -- Policy: Team members can view opportunities
93
+ CREATE POLICY "opportunities_select_policy" ON "opportunities"
94
+ FOR SELECT
95
+ USING (
96
+ "teamId" = ANY(public.get_user_team_ids())
97
+ OR public.is_superadmin()
98
+ );
99
+
100
+ -- Policy: Team members can create opportunities
101
+ CREATE POLICY "opportunities_insert_policy" ON "opportunities"
102
+ FOR INSERT
103
+ WITH CHECK (
104
+ "teamId" = ANY(public.get_user_team_ids())
105
+ );
106
+
107
+ -- Policy: Team members can update opportunities
108
+ CREATE POLICY "opportunities_update_policy" ON "opportunities"
109
+ FOR UPDATE
110
+ USING (
111
+ "teamId" = ANY(public.get_user_team_ids())
112
+ OR public.is_superadmin()
113
+ );
114
+
115
+ -- Policy: Team members can delete opportunities
116
+ CREATE POLICY "opportunities_delete_policy" ON "opportunities"
117
+ FOR DELETE
118
+ USING (
119
+ "teamId" = ANY(public.get_user_team_ids())
120
+ OR public.is_superadmin()
121
+ );
122
+
123
+ -- ============================================
124
+ -- TRIGGER updatedAt
125
+ -- ============================================
126
+ CREATE OR REPLACE FUNCTION update_opportunities_updated_at()
127
+ RETURNS TRIGGER AS $$
128
+ BEGIN
129
+ NEW."updatedAt" = NOW();
130
+ RETURN NEW;
131
+ END;
132
+ $$ LANGUAGE plpgsql;
133
+
134
+ DROP TRIGGER IF EXISTS opportunities_updated_at_trigger ON "opportunities";
135
+ CREATE TRIGGER opportunities_updated_at_trigger
136
+ BEFORE UPDATE ON "opportunities"
137
+ FOR EACH ROW
138
+ EXECUTE FUNCTION update_opportunities_updated_at();
139
+
140
+ -- ============================================
141
+ -- COMMENTS
142
+ -- ============================================
143
+ COMMENT ON TABLE "opportunities" IS 'Sales opportunities in the pipeline';
144
+ COMMENT ON COLUMN "opportunities"."expectedRevenue" IS 'Calculated as amount * (probability / 100)';
145
+ COMMENT ON COLUMN "opportunities"."stageId" IS 'Current stage ID from pipeline stages JSONB';
@@ -0,0 +1,114 @@
1
+ -- Migration: 002_opportunities_metas.sql
2
+ -- Description: Contacts metas (table, indexes, RLS)
3
+ -- Date: 2025-09-27
4
+
5
+ -- ============================================
6
+ -- TABLE
7
+ -- ============================================
8
+ -- No DROP needed - removed automatically by parent table CASCADE
9
+ CREATE TABLE IF NOT EXISTS public."opportunities_metas" (
10
+ id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
11
+ "entityId" TEXT NOT NULL REFERENCES public."opportunities"(id) ON DELETE CASCADE,
12
+ "metaKey" TEXT NOT NULL,
13
+ "metaValue" JSONB NOT NULL DEFAULT '{}'::jsonb,
14
+ "dataType" TEXT DEFAULT 'json',
15
+ "isPublic" BOOLEAN NOT NULL DEFAULT false,
16
+ "isSearchable" BOOLEAN NOT NULL DEFAULT false,
17
+ "createdAt" TIMESTAMPTZ NOT NULL DEFAULT now(),
18
+ "updatedAt" TIMESTAMPTZ NOT NULL DEFAULT now(),
19
+ CONSTRAINT opportunities_metas_unique_key UNIQUE ("entityId", "metaKey")
20
+ );
21
+
22
+ COMMENT ON TABLE public."opportunities_metas" IS 'Contacts metadata table - stores additional key-value pairs for opportunities';
23
+ COMMENT ON COLUMN public."opportunities_metas"."entityId" IS 'Generic foreign key to parent opportunitie entity';
24
+ COMMENT ON COLUMN public."opportunities_metas"."metaKey" IS 'Metadata key name';
25
+ COMMENT ON COLUMN public."opportunities_metas"."metaValue" IS 'Metadata value as JSONB';
26
+ COMMENT ON COLUMN public."opportunities_metas"."dataType" IS 'Type hint for the value: json, string, number, boolean';
27
+ COMMENT ON COLUMN public."opportunities_metas"."isPublic" IS 'Whether this metadata is publicly readable';
28
+ COMMENT ON COLUMN public."opportunities_metas"."isSearchable" IS 'Whether this metadata is searchable';
29
+
30
+ -- ============================================
31
+ -- TRIGGER updatedAt (uses Better Auth function)
32
+ -- ============================================
33
+ DROP TRIGGER IF EXISTS opportunities_metas_set_updated_at ON public."opportunities_metas";
34
+ CREATE TRIGGER opportunities_metas_set_updated_at
35
+ BEFORE UPDATE ON public."opportunities_metas"
36
+ FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
37
+
38
+ -- ============================================
39
+ -- INDEXES
40
+ -- ============================================
41
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_entity_id ON public."opportunities_metas"("entityId");
42
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_key ON public."opportunities_metas"("metaKey");
43
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_composite ON public."opportunities_metas"("entityId", "metaKey", "isPublic");
44
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_is_public ON public."opportunities_metas"("isPublic") WHERE "isPublic" = true;
45
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_is_searchable ON public."opportunities_metas"("isSearchable") WHERE "isSearchable" = true;
46
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_searchable_key ON public."opportunities_metas"("metaKey") WHERE "isSearchable" = true;
47
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_value_gin ON public."opportunities_metas" USING GIN ("metaValue");
48
+ CREATE INDEX IF NOT EXISTS idx_opportunities_metas_value_ops ON public."opportunities_metas" USING GIN ("metaValue" jsonb_path_ops);
49
+
50
+ -- ============================================
51
+ -- RLS
52
+ -- ============================================
53
+ ALTER TABLE public."opportunities_metas" ENABLE ROW LEVEL SECURITY;
54
+
55
+ -- Cleanup existing policies
56
+ DROP POLICY IF EXISTS "Users can view opportunitie metas" ON public."opportunities_metas";
57
+ DROP POLICY IF EXISTS "Users can create opportunitie metas" ON public."opportunities_metas";
58
+ DROP POLICY IF EXISTS "Users can update opportunitie metas" ON public."opportunities_metas";
59
+ DROP POLICY IF EXISTS "Users can delete opportunitie metas" ON public."opportunities_metas";
60
+
61
+ -- ============================
62
+ -- AUTHENTICATED USER POLICIES
63
+ -- ============================
64
+ -- Inherit permissions from parent entity
65
+ CREATE POLICY "Users can view opportunitie metas"
66
+ ON public."opportunities_metas"
67
+ FOR SELECT TO authenticated
68
+ USING (
69
+ EXISTS (
70
+ SELECT 1 FROM public."opportunities" c
71
+ WHERE c.id = "entityId"
72
+ AND c."userId" = public.get_auth_user_id()
73
+ )
74
+ );
75
+
76
+ CREATE POLICY "Users can create opportunitie metas"
77
+ ON public."opportunities_metas"
78
+ FOR INSERT TO authenticated
79
+ WITH CHECK (
80
+ EXISTS (
81
+ SELECT 1 FROM public."opportunities" c
82
+ WHERE c.id = "entityId"
83
+ AND c."userId" = public.get_auth_user_id()
84
+ )
85
+ );
86
+
87
+ CREATE POLICY "Users can update opportunitie metas"
88
+ ON public."opportunities_metas"
89
+ FOR UPDATE TO authenticated
90
+ USING (
91
+ EXISTS (
92
+ SELECT 1 FROM public."opportunities" c
93
+ WHERE c.id = "entityId"
94
+ AND c."userId" = public.get_auth_user_id()
95
+ )
96
+ )
97
+ WITH CHECK (
98
+ EXISTS (
99
+ SELECT 1 FROM public."opportunities" c
100
+ WHERE c.id = "entityId"
101
+ AND c."userId" = public.get_auth_user_id()
102
+ )
103
+ );
104
+
105
+ CREATE POLICY "Users can delete opportunitie metas"
106
+ ON public."opportunities_metas"
107
+ FOR DELETE TO authenticated
108
+ USING (
109
+ EXISTS (
110
+ SELECT 1 FROM public."opportunities" c
111
+ WHERE c.id = "entityId"
112
+ AND c."userId" = public.get_auth_user_id()
113
+ )
114
+ );
@@ -0,0 +1,438 @@
1
+ -- ============================================================================
2
+ -- Sample data for opportunities table - CRM Theme
3
+ -- Aligned with schema in 001_opportunities_table.sql
4
+ -- Uses users from 999_theme_sample_data.sql
5
+ -- References companies, contacts, and pipelines from their sample data
6
+ -- NOTE: expectedRevenue is a GENERATED column - DO NOT insert it!
7
+ -- ============================================================================
8
+
9
+ -- Clean existing opportunities data
10
+ DELETE FROM "opportunities" WHERE "teamId" = 'team-crm-company';
11
+
12
+ INSERT INTO "opportunities" (
13
+ id,
14
+ name,
15
+ "companyId",
16
+ "contactId",
17
+ "pipelineId",
18
+ "stageId",
19
+ amount,
20
+ currency,
21
+ probability,
22
+ "closeDate",
23
+ "wonDate",
24
+ "lostDate",
25
+ type,
26
+ source,
27
+ competitor,
28
+ status,
29
+ "lostReason",
30
+ "assignedTo",
31
+ "userId",
32
+ "teamId",
33
+ "createdAt",
34
+ "updatedAt"
35
+ ) VALUES
36
+ -- TechnoSoft Solutions Opportunities (company-crm-001)
37
+ (
38
+ 'opp-crm-001',
39
+ 'TechnoSoft CRM Enterprise Implementation',
40
+ 'company-crm-001',
41
+ 'contact-crm-001',
42
+ 'cf7f1f00-0002-4000-8000-000000000002',
43
+ 'stage_011',
44
+ 125000.00,
45
+ 'USD',
46
+ 80,
47
+ DATE(NOW() + INTERVAL '45 days'),
48
+ NULL,
49
+ NULL,
50
+ 'new_business',
51
+ 'referral',
52
+ 'Salesforce',
53
+ 'open',
54
+ NULL,
55
+ 'usr-crm-sales-mgr',
56
+ 'usr-crm-ceo',
57
+ 'team-crm-company',
58
+ NOW() - INTERVAL '35 days',
59
+ NOW() - INTERVAL '2 days'
60
+ ),
61
+ (
62
+ 'opp-crm-002',
63
+ 'TechnoSoft Analytics Module Upgrade',
64
+ 'company-crm-001',
65
+ 'contact-crm-003',
66
+ 'cf7f1f00-0001-4000-8000-000000000001',
67
+ 'stage_003',
68
+ 15000.00,
69
+ 'USD',
70
+ 50,
71
+ DATE(NOW() + INTERVAL '30 days'),
72
+ NULL,
73
+ NULL,
74
+ 'existing_business',
75
+ 'existing_customer',
76
+ NULL,
77
+ 'open',
78
+ NULL,
79
+ 'usr-crm-sales-rep',
80
+ 'usr-crm-sales-mgr',
81
+ 'team-crm-company',
82
+ NOW() - INTERVAL '20 days',
83
+ NOW() - INTERVAL '3 days'
84
+ ),
85
+
86
+ -- Global Manufacturing Corp Opportunities (company-crm-002)
87
+ (
88
+ 'opp-crm-003',
89
+ 'Global Manufacturing Digital Transformation',
90
+ 'company-crm-002',
91
+ 'contact-crm-004',
92
+ 'cf7f1f00-0002-4000-8000-000000000002',
93
+ 'stage_009',
94
+ 250000.00,
95
+ 'USD',
96
+ 30,
97
+ DATE(NOW() + INTERVAL '90 days'),
98
+ NULL,
99
+ NULL,
100
+ 'new_business',
101
+ 'trade_show',
102
+ 'HubSpot',
103
+ 'open',
104
+ NULL,
105
+ 'usr-crm-sales-rep',
106
+ 'usr-crm-sales-mgr',
107
+ 'team-crm-company',
108
+ NOW() - INTERVAL '60 days',
109
+ NOW() - INTERVAL '5 days'
110
+ ),
111
+ (
112
+ 'opp-crm-004',
113
+ 'Manufacturing Training & Support Package',
114
+ 'company-crm-002',
115
+ 'contact-crm-005',
116
+ 'cf7f1f00-0001-4000-8000-000000000001',
117
+ 'stage_004',
118
+ 35000.00,
119
+ 'USD',
120
+ 75,
121
+ DATE(NOW() + INTERVAL '20 days'),
122
+ NULL,
123
+ NULL,
124
+ 'existing_business',
125
+ 'existing_customer',
126
+ NULL,
127
+ 'open',
128
+ NULL,
129
+ 'usr-crm-sales-rep',
130
+ 'usr-crm-sales-mgr',
131
+ 'team-crm-company',
132
+ NOW() - INTERVAL '25 days',
133
+ NOW() - INTERVAL '1 day'
134
+ ),
135
+
136
+ -- Healthcare Innovations Opportunities (company-crm-003)
137
+ (
138
+ 'opp-crm-005',
139
+ 'Healthcare CRM Pro Implementation',
140
+ 'company-crm-003',
141
+ 'contact-crm-006',
142
+ 'cf7f1f00-0001-4000-8000-000000000001',
143
+ 'stage_002',
144
+ 45000.00,
145
+ 'USD',
146
+ 25,
147
+ DATE(NOW() + INTERVAL '60 days'),
148
+ NULL,
149
+ NULL,
150
+ 'new_business',
151
+ 'linkedin',
152
+ 'Zoho',
153
+ 'open',
154
+ NULL,
155
+ 'usr-crm-sales-mgr',
156
+ 'usr-crm-ceo',
157
+ 'team-crm-company',
158
+ NOW() - INTERVAL '15 days',
159
+ NOW() - INTERVAL '1 day'
160
+ ),
161
+ (
162
+ 'opp-crm-006',
163
+ 'Healthcare Compliance & Security Audit',
164
+ 'company-crm-003',
165
+ 'contact-crm-007',
166
+ 'cf7f1f00-0001-4000-8000-000000000001',
167
+ 'stage_001',
168
+ 12000.00,
169
+ 'USD',
170
+ 10,
171
+ DATE(NOW() + INTERVAL '75 days'),
172
+ NULL,
173
+ NULL,
174
+ 'new_business',
175
+ 'referral',
176
+ NULL,
177
+ 'open',
178
+ NULL,
179
+ 'usr-crm-sales-rep',
180
+ 'usr-crm-sales-mgr',
181
+ 'team-crm-company',
182
+ NOW() - INTERVAL '10 days',
183
+ NOW() - INTERVAL '2 days'
184
+ ),
185
+
186
+ -- FinanceFirst Bank Opportunities (company-crm-004)
187
+ (
188
+ 'opp-crm-007',
189
+ 'FinanceFirst Enterprise CRM Platform',
190
+ 'company-crm-004',
191
+ 'contact-crm-008',
192
+ 'cf7f1f00-0002-4000-8000-000000000002',
193
+ 'stage_010',
194
+ 180000.00,
195
+ 'USD',
196
+ 60,
197
+ DATE(NOW() + INTERVAL '120 days'),
198
+ NULL,
199
+ NULL,
200
+ 'existing_business',
201
+ 'existing_customer',
202
+ 'Microsoft Dynamics',
203
+ 'open',
204
+ NULL,
205
+ 'usr-crm-sales-rep',
206
+ 'usr-crm-sales-mgr',
207
+ 'team-crm-company',
208
+ NOW() - INTERVAL '90 days',
209
+ NOW() - INTERVAL '10 days'
210
+ ),
211
+
212
+ -- EduTech Academy Opportunities (company-crm-005)
213
+ (
214
+ 'opp-crm-008',
215
+ 'EduTech CRM Pro License & Training',
216
+ 'company-crm-005',
217
+ 'contact-crm-010',
218
+ 'cf7f1f00-0001-4000-8000-000000000001',
219
+ 'stage_003',
220
+ 28000.00,
221
+ 'USD',
222
+ 50,
223
+ DATE(NOW() + INTERVAL '35 days'),
224
+ NULL,
225
+ NULL,
226
+ 'new_business',
227
+ 'webinar',
228
+ NULL,
229
+ 'open',
230
+ NULL,
231
+ 'usr-crm-sales-rep',
232
+ 'usr-crm-sales-mgr',
233
+ 'team-crm-company',
234
+ NOW() - INTERVAL '12 days',
235
+ NOW() - INTERVAL '1 day'
236
+ ),
237
+
238
+ -- RetailMax Chain Opportunities (company-crm-006)
239
+ (
240
+ 'opp-crm-009',
241
+ 'RetailMax Multi-Store CRM Solution',
242
+ 'company-crm-006',
243
+ 'contact-crm-012',
244
+ 'cf7f1f00-0002-4000-8000-000000000002',
245
+ 'stage_008',
246
+ 95000.00,
247
+ 'USD',
248
+ 15,
249
+ DATE(NOW() + INTERVAL '150 days'),
250
+ NULL,
251
+ NULL,
252
+ 'new_business',
253
+ 'partner_referral',
254
+ 'Pipedrive',
255
+ 'open',
256
+ NULL,
257
+ 'usr-crm-sales-mgr',
258
+ 'usr-crm-ceo',
259
+ 'team-crm-company',
260
+ NOW() - INTERVAL '45 days',
261
+ NOW() - INTERVAL '7 days'
262
+ ),
263
+
264
+ -- StartupTech Inc Opportunities (company-crm-007)
265
+ (
266
+ 'opp-crm-010',
267
+ 'StartupTech Growth Package',
268
+ 'company-crm-007',
269
+ 'contact-crm-014',
270
+ 'cf7f1f00-0003-4000-8000-000000000003',
271
+ 'stage_017',
272
+ 8500.00,
273
+ 'USD',
274
+ 60,
275
+ DATE(NOW() + INTERVAL '25 days'),
276
+ NULL,
277
+ NULL,
278
+ 'new_business',
279
+ 'inbound_marketing',
280
+ NULL,
281
+ 'open',
282
+ NULL,
283
+ 'usr-crm-sales-rep',
284
+ 'usr-crm-sales-rep',
285
+ 'team-crm-company',
286
+ NOW() - INTERVAL '8 days',
287
+ NOW() - INTERVAL '1 day'
288
+ ),
289
+ (
290
+ 'opp-crm-011',
291
+ 'StartupTech Implementation Services',
292
+ 'company-crm-007',
293
+ 'contact-crm-015',
294
+ 'cf7f1f00-0001-4000-8000-000000000001',
295
+ 'stage_002',
296
+ 15000.00,
297
+ 'USD',
298
+ 25,
299
+ DATE(NOW() + INTERVAL '40 days'),
300
+ NULL,
301
+ NULL,
302
+ 'new_business',
303
+ 'referral',
304
+ NULL,
305
+ 'open',
306
+ NULL,
307
+ 'usr-crm-sales-rep',
308
+ 'usr-crm-sales-rep',
309
+ 'team-crm-company',
310
+ NOW() - INTERVAL '5 days',
311
+ NOW() - INTERVAL '1 day'
312
+ ),
313
+
314
+ -- Local Consulting Group Opportunities (company-crm-008)
315
+ (
316
+ 'opp-crm-012',
317
+ 'Local Consulting CRM Setup',
318
+ 'company-crm-008',
319
+ 'contact-crm-016',
320
+ 'cf7f1f00-0003-4000-8000-000000000003',
321
+ 'stage_015',
322
+ 6500.00,
323
+ 'USD',
324
+ 15,
325
+ DATE(NOW() + INTERVAL '50 days'),
326
+ NULL,
327
+ NULL,
328
+ 'new_business',
329
+ 'cold_outreach',
330
+ NULL,
331
+ 'open',
332
+ NULL,
333
+ 'usr-crm-sales-rep',
334
+ 'usr-crm-sales-mgr',
335
+ 'team-crm-company',
336
+ NOW() - INTERVAL '20 days',
337
+ NOW() - INTERVAL '5 days'
338
+ ),
339
+
340
+ -- Closed Won Opportunities (Historical Data)
341
+ (
342
+ 'opp-crm-013',
343
+ 'TechnoSoft Initial CRM License',
344
+ 'company-crm-001',
345
+ 'contact-crm-001',
346
+ 'cf7f1f00-0001-4000-8000-000000000001',
347
+ 'stage_005',
348
+ 18000.00,
349
+ 'USD',
350
+ 100,
351
+ DATE(NOW() - INTERVAL '30 days'),
352
+ DATE(NOW() - INTERVAL '30 days'),
353
+ NULL,
354
+ 'new_business',
355
+ 'referral',
356
+ NULL,
357
+ 'won',
358
+ NULL,
359
+ 'usr-crm-sales-mgr',
360
+ 'usr-crm-ceo',
361
+ 'team-crm-company',
362
+ NOW() - INTERVAL '75 days',
363
+ NOW() - INTERVAL '30 days'
364
+ ),
365
+ (
366
+ 'opp-crm-014',
367
+ 'Global Manufacturing Server Package',
368
+ 'company-crm-002',
369
+ 'contact-crm-004',
370
+ 'cf7f1f00-0001-4000-8000-000000000001',
371
+ 'stage_005',
372
+ 42000.00,
373
+ 'USD',
374
+ 100,
375
+ DATE(NOW() - INTERVAL '15 days'),
376
+ DATE(NOW() - INTERVAL '15 days'),
377
+ NULL,
378
+ 'new_business',
379
+ 'existing_customer',
380
+ NULL,
381
+ 'won',
382
+ NULL,
383
+ 'usr-crm-sales-rep',
384
+ 'usr-crm-sales-mgr',
385
+ 'team-crm-company',
386
+ NOW() - INTERVAL '60 days',
387
+ NOW() - INTERVAL '15 days'
388
+ ),
389
+
390
+ -- Closed Lost Opportunities (Learning Data)
391
+ (
392
+ 'opp-crm-015',
393
+ 'Healthcare Budget Constraints Deal',
394
+ 'company-crm-003',
395
+ 'contact-crm-006',
396
+ 'cf7f1f00-0001-4000-8000-000000000001',
397
+ 'stage_006',
398
+ 65000.00,
399
+ 'USD',
400
+ 0,
401
+ DATE(NOW() - INTERVAL '10 days'),
402
+ NULL,
403
+ DATE(NOW() - INTERVAL '10 days'),
404
+ 'new_business',
405
+ 'trade_show',
406
+ 'Salesforce',
407
+ 'lost',
408
+ 'Budget constraints due to Q4 freezing',
409
+ 'usr-crm-sales-mgr',
410
+ 'usr-crm-ceo',
411
+ 'team-crm-company',
412
+ NOW() - INTERVAL '90 days',
413
+ NOW() - INTERVAL '10 days'
414
+ ),
415
+ (
416
+ 'opp-crm-016',
417
+ 'StartupTech Timing Issues',
418
+ 'company-crm-007',
419
+ 'contact-crm-014',
420
+ 'cf7f1f00-0003-4000-8000-000000000003',
421
+ 'stage_019',
422
+ 12000.00,
423
+ 'USD',
424
+ 0,
425
+ DATE(NOW() - INTERVAL '5 days'),
426
+ NULL,
427
+ DATE(NOW() - INTERVAL '5 days'),
428
+ 'new_business',
429
+ 'website',
430
+ NULL,
431
+ 'lost',
432
+ 'Not the right timing - revisit in 6 months',
433
+ 'usr-crm-sales-rep',
434
+ 'usr-crm-sales-rep',
435
+ 'team-crm-company',
436
+ NOW() - INTERVAL '45 days',
437
+ NOW() - INTERVAL '5 days'
438
+ );