@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.
- package/CRM_PLAN.md +343 -0
- package/about.md +122 -0
- package/config/app.config.ts +185 -0
- package/config/billing.config.ts +187 -0
- package/config/dashboard.config.ts +372 -0
- package/config/dev.config.ts +55 -0
- package/config/features.config.ts +336 -0
- package/config/flows.config.ts +511 -0
- package/config/permissions.config.ts +297 -0
- package/config/theme.config.ts +111 -0
- package/entities/activities/activities.config.ts +61 -0
- package/entities/activities/activities.fields.ts +362 -0
- package/entities/activities/activities.service.ts +503 -0
- package/entities/activities/activities.types.ts +117 -0
- package/entities/activities/messages/en.json +123 -0
- package/entities/activities/messages/es.json +123 -0
- package/entities/activities/migrations/020_activities_table.sql +123 -0
- package/entities/activities/migrations/021_activities_metas.sql +114 -0
- package/entities/activities/migrations/022_activities_sample_data.sql +420 -0
- package/entities/campaigns/campaigns.config.ts +61 -0
- package/entities/campaigns/campaigns.fields.ts +413 -0
- package/entities/campaigns/campaigns.service.ts +426 -0
- package/entities/campaigns/campaigns.types.ts +124 -0
- package/entities/campaigns/messages/en.json +145 -0
- package/entities/campaigns/messages/es.json +145 -0
- package/entities/campaigns/migrations/001_campaigns_table.sql +127 -0
- package/entities/campaigns/migrations/002_campaigns_metas.sql +114 -0
- package/entities/campaigns/migrations/003_campaigns_sample_data.sql +364 -0
- package/entities/companies/companies.config.ts +61 -0
- package/entities/companies/companies.fields.ts +429 -0
- package/entities/companies/companies.service.ts +566 -0
- package/entities/companies/companies.types.ts +125 -0
- package/entities/companies/messages/en.json +146 -0
- package/entities/companies/messages/es.json +146 -0
- package/entities/companies/migrations/001_companies_table.sql +150 -0
- package/entities/companies/migrations/002_companies_metas.sql +114 -0
- package/entities/companies/migrations/003_companies_sample_data.sql +246 -0
- package/entities/contacts/contacts.config.ts +61 -0
- package/entities/contacts/contacts.fields.ts +359 -0
- package/entities/contacts/contacts.service.ts +509 -0
- package/entities/contacts/contacts.types.ts +108 -0
- package/entities/contacts/messages/en.json +117 -0
- package/entities/contacts/messages/es.json +117 -0
- package/entities/contacts/migrations/001_contacts_table.sql +134 -0
- package/entities/contacts/migrations/002_contacts_metas.sql +114 -0
- package/entities/contacts/migrations/003_contacts_sample_data.sql +421 -0
- package/entities/leads/leads.config.ts +61 -0
- package/entities/leads/leads.fields.ts +336 -0
- package/entities/leads/leads.service.ts +496 -0
- package/entities/leads/leads.types.ts +114 -0
- package/entities/leads/messages/en.json +132 -0
- package/entities/leads/messages/es.json +132 -0
- package/entities/leads/migrations/001_leads_table.sql +150 -0
- package/entities/leads/migrations/002_leads_metas.sql +120 -0
- package/entities/leads/migrations/003_leads_sample_data.sql +242 -0
- package/entities/notes/messages/en.json +114 -0
- package/entities/notes/messages/es.json +114 -0
- package/entities/notes/migrations/020_notes_table.sql +118 -0
- package/entities/notes/migrations/021_notes_metas.sql +114 -0
- package/entities/notes/migrations/022_notes_sample_data.sql +275 -0
- package/entities/notes/notes.config.ts +61 -0
- package/entities/notes/notes.fields.ts +283 -0
- package/entities/notes/notes.service.ts +320 -0
- package/entities/notes/notes.types.ts +102 -0
- package/entities/opportunities/messages/en.json +107 -0
- package/entities/opportunities/messages/es.json +107 -0
- package/entities/opportunities/migrations/010_opportunities_table.sql +145 -0
- package/entities/opportunities/migrations/011_opportunities_metas.sql +114 -0
- package/entities/opportunities/migrations/012_opportunities_sample_data.sql +438 -0
- package/entities/opportunities/opportunities.config.ts +61 -0
- package/entities/opportunities/opportunities.fields.ts +416 -0
- package/entities/opportunities/opportunities.service.ts +525 -0
- package/entities/opportunities/opportunities.types.ts +135 -0
- package/entities/pipelines/messages/en.json +115 -0
- package/entities/pipelines/messages/es.json +115 -0
- package/entities/pipelines/migrations/001_pipelines_table.sql +106 -0
- package/entities/pipelines/migrations/002_pipelines_metas.sql +114 -0
- package/entities/pipelines/migrations/003_pipelines_sample_data.sql +91 -0
- package/entities/pipelines/pipelines.config.ts +62 -0
- package/entities/pipelines/pipelines.fields.ts +193 -0
- package/entities/pipelines/pipelines.service.ts +383 -0
- package/entities/pipelines/pipelines.types.ts +78 -0
- package/entities/products/messages/en.json +135 -0
- package/entities/products/messages/es.json +135 -0
- package/entities/products/migrations/001_products_table.sql +117 -0
- package/entities/products/migrations/002_products_metas.sql +114 -0
- package/entities/products/migrations/003_products_sample_data.sql +247 -0
- package/entities/products/products.config.ts +62 -0
- package/entities/products/products.fields.ts +361 -0
- package/entities/products/products.service.ts +437 -0
- package/entities/products/products.types.ts +125 -0
- package/lib/crm-constants.ts +77 -0
- package/lib/crm-utils.ts +185 -0
- package/lib/selectors.ts +333 -0
- package/messages/en.json +131 -0
- package/messages/es.json +131 -0
- package/migrations/999_theme_sample_data.sql +473 -0
- package/package.json +18 -0
- package/pendings.md +205 -0
- package/permissions-matrix.md +216 -0
- package/styles/components.css +414 -0
- package/styles/crm-theme.css +358 -0
- package/styles/globals.css +576 -0
- package/styles/variables.css +111 -0
- package/templates/dashboard/(main)/activities/components/ActivityCard.tsx +169 -0
- package/templates/dashboard/(main)/activities/components/ActivityTimeline.tsx +165 -0
- package/templates/dashboard/(main)/activities/page.tsx +297 -0
- package/templates/dashboard/(main)/campaigns/page.tsx +373 -0
- package/templates/dashboard/(main)/companies/page.tsx +296 -0
- package/templates/dashboard/(main)/contacts/page.tsx +347 -0
- package/templates/dashboard/(main)/layout.tsx +98 -0
- package/templates/dashboard/(main)/leads/page.tsx +335 -0
- package/templates/dashboard/(main)/opportunities/[id]/edit/page.tsx +95 -0
- package/templates/dashboard/(main)/opportunities/create/page.tsx +94 -0
- package/templates/dashboard/(main)/opportunities/page.tsx +350 -0
- package/templates/dashboard/(main)/pipelines/[id]/edit/page.tsx +95 -0
- package/templates/dashboard/(main)/pipelines/[id]/page.tsx +143 -0
- package/templates/dashboard/(main)/pipelines/create/page.tsx +94 -0
- package/templates/dashboard/(main)/pipelines/page.tsx +234 -0
- package/templates/dashboard/(main)/products/[id]/edit/page.tsx +97 -0
- package/templates/dashboard/(main)/products/[id]/page.tsx +509 -0
- package/templates/dashboard/(main)/products/create/page.tsx +96 -0
- package/templates/dashboard/(main)/products/page.tsx +308 -0
- package/templates/shared/ActionButtons.tsx +41 -0
- package/templates/shared/CRMDashboard.tsx +519 -0
- package/templates/shared/CRMDataTable.tsx +441 -0
- package/templates/shared/CRMMetricCard.tsx +76 -0
- package/templates/shared/CRMMobileNav.tsx +172 -0
- package/templates/shared/CRMSidebar.tsx +346 -0
- package/templates/shared/CRMTopBar.tsx +265 -0
- package/templates/shared/DealCard.tsx +123 -0
- package/templates/shared/EntityCard.tsx +58 -0
- package/templates/shared/OpportunityForm.tsx +649 -0
- package/templates/shared/PipelineForm.tsx +367 -0
- package/templates/shared/PipelineKanban.tsx +194 -0
- package/templates/shared/QuickFilters.tsx +47 -0
- package/templates/shared/StageColumn.tsx +175 -0
- package/templates/shared/StageSelect.tsx +177 -0
- package/templates/shared/StagesRepeater.tsx +317 -0
- package/templates/shared/index.ts +9 -0
package/CRM_PLAN.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# Plan de Implementación del Sistema CRM
|
|
2
|
+
|
|
3
|
+
## Estado: EN DESARROLLO
|
|
4
|
+
## Fecha: 2025-09-27
|
|
5
|
+
|
|
6
|
+
## Entidades del CRM (9 entidades fundamentales)
|
|
7
|
+
|
|
8
|
+
### 1. LEADS
|
|
9
|
+
**Descripción**: Prospectos potenciales que aún no son clientes
|
|
10
|
+
**Tabla**: `leads`
|
|
11
|
+
**Campos**:
|
|
12
|
+
- `id` (TEXT/UUID) - Primary key
|
|
13
|
+
- `userId` (TEXT) - User who owns this lead
|
|
14
|
+
- `companyName` (TEXT) - Company name
|
|
15
|
+
- `contactName` (TEXT) - Contact person name
|
|
16
|
+
- `email` (TEXT) - Email address
|
|
17
|
+
- `phone` (TEXT) - Phone number
|
|
18
|
+
- `website` (TEXT) - Company website
|
|
19
|
+
- `source` (TEXT) - Lead source (web, referral, cold_call, trade_show, social_media)
|
|
20
|
+
- `status` (TEXT) - Lead status (new, contacted, qualified, proposal, negotiation, converted, lost)
|
|
21
|
+
- `score` (INTEGER) - Lead score (0-100)
|
|
22
|
+
- `industry` (TEXT) - Industry sector
|
|
23
|
+
- `companySize` (TEXT) - Company size (1-10, 11-50, 51-200, 201-500, 500+)
|
|
24
|
+
- `budget` (DECIMAL) - Estimated budget
|
|
25
|
+
- `assignedTo` (TEXT) - User ID of assigned sales rep
|
|
26
|
+
- `convertedDate` (TIMESTAMPTZ) - Date when lead was converted
|
|
27
|
+
- `convertedToContactId` (TEXT) - Reference to contact if converted
|
|
28
|
+
- `convertedToCompanyId` (TEXT) - Reference to company if converted
|
|
29
|
+
- `notes` (TEXT) - Internal notes
|
|
30
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
31
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
32
|
+
|
|
33
|
+
### 2. CONTACTS
|
|
34
|
+
**Descripción**: Personas de contacto en las empresas
|
|
35
|
+
**Tabla**: `contacts`
|
|
36
|
+
**Campos**:
|
|
37
|
+
- `id` (TEXT/UUID) - Primary key
|
|
38
|
+
- `userId` (TEXT) - User who owns this contact
|
|
39
|
+
- `companyId` (TEXT) - Reference to companies table (nullable for standalone contacts)
|
|
40
|
+
- `firstName` (TEXT) - First name
|
|
41
|
+
- `lastName` (TEXT) - Last name
|
|
42
|
+
- `email` (TEXT) - Email address
|
|
43
|
+
- `phone` (TEXT) - Phone number
|
|
44
|
+
- `mobile` (TEXT) - Mobile phone
|
|
45
|
+
- `position` (TEXT) - Job position/title
|
|
46
|
+
- `department` (TEXT) - Department
|
|
47
|
+
- `isPrimary` (BOOLEAN) - Is primary contact for company
|
|
48
|
+
- `birthDate` (DATE) - Birth date
|
|
49
|
+
- `linkedin` (TEXT) - LinkedIn profile URL
|
|
50
|
+
- `twitter` (TEXT) - Twitter handle
|
|
51
|
+
- `preferredChannel` (TEXT) - Preferred contact channel (email, phone, whatsapp, linkedin)
|
|
52
|
+
- `timezone` (TEXT) - Contact's timezone
|
|
53
|
+
- `lastContactedAt` (TIMESTAMPTZ) - Last contact date
|
|
54
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
55
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
56
|
+
|
|
57
|
+
### 3. COMPANIES
|
|
58
|
+
**Descripción**: Empresas clientes o prospectos
|
|
59
|
+
**Tabla**: `companies`
|
|
60
|
+
**Campos**:
|
|
61
|
+
- `id` (TEXT/UUID) - Primary key
|
|
62
|
+
- `userId` (TEXT) - User who owns this company
|
|
63
|
+
- `name` (TEXT) - Company name
|
|
64
|
+
- `legalName` (TEXT) - Legal company name
|
|
65
|
+
- `taxId` (TEXT) - Tax identification number
|
|
66
|
+
- `website` (TEXT) - Company website
|
|
67
|
+
- `email` (TEXT) - General company email
|
|
68
|
+
- `phone` (TEXT) - Main phone number
|
|
69
|
+
- `industry` (TEXT) - Industry sector
|
|
70
|
+
- `type` (TEXT) - Company type (prospect, customer, partner, competitor)
|
|
71
|
+
- `size` (TEXT) - Company size (1-10, 11-50, 51-200, 201-500, 500+)
|
|
72
|
+
- `annualRevenue` (DECIMAL) - Annual revenue
|
|
73
|
+
- `address` (TEXT) - Street address
|
|
74
|
+
- `city` (TEXT) - City
|
|
75
|
+
- `state` (TEXT) - State/Province
|
|
76
|
+
- `country` (TEXT) - Country
|
|
77
|
+
- `postalCode` (TEXT) - Postal/ZIP code
|
|
78
|
+
- `logo` (TEXT) - Logo URL
|
|
79
|
+
- `linkedin` (TEXT) - LinkedIn company page
|
|
80
|
+
- `facebook` (TEXT) - Facebook page
|
|
81
|
+
- `twitter` (TEXT) - Twitter handle
|
|
82
|
+
- `rating` (TEXT) - Company rating (hot, warm, cold)
|
|
83
|
+
- `assignedTo` (TEXT) - User ID of account manager
|
|
84
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
85
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
86
|
+
|
|
87
|
+
### 4. OPPORTUNITIES
|
|
88
|
+
**Descripción**: Oportunidades de venta
|
|
89
|
+
**Tabla**: `opportunities`
|
|
90
|
+
**Campos**:
|
|
91
|
+
- `id` (TEXT/UUID) - Primary key
|
|
92
|
+
- `userId` (TEXT) - User who owns this opportunity
|
|
93
|
+
- `name` (TEXT) - Opportunity name
|
|
94
|
+
- `companyId` (TEXT) - Reference to companies table
|
|
95
|
+
- `contactId` (TEXT) - Primary contact for this opportunity
|
|
96
|
+
- `pipelineId` (TEXT) - Reference to pipelines table
|
|
97
|
+
- `stageId` (TEXT) - Current stage in pipeline
|
|
98
|
+
- `amount` (DECIMAL) - Deal amount
|
|
99
|
+
- `currency` (TEXT) - Currency code (USD, EUR, MXN)
|
|
100
|
+
- `probability` (INTEGER) - Win probability (0-100)
|
|
101
|
+
- `expectedRevenue` (DECIMAL) - amount * (probability/100)
|
|
102
|
+
- `closeDate` (DATE) - Expected close date
|
|
103
|
+
- `type` (TEXT) - Opportunity type (new_business, existing_business, renewal)
|
|
104
|
+
- `source` (TEXT) - Lead source
|
|
105
|
+
- `competitor` (TEXT) - Main competitor
|
|
106
|
+
- `status` (TEXT) - Status (open, won, lost)
|
|
107
|
+
- `lostReason` (TEXT) - Reason if lost
|
|
108
|
+
- `wonDate` (DATE) - Date when won
|
|
109
|
+
- `lostDate` (DATE) - Date when lost
|
|
110
|
+
- `assignedTo` (TEXT) - User ID of sales rep
|
|
111
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
112
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
113
|
+
|
|
114
|
+
### 5. ACTIVITIES
|
|
115
|
+
**Descripción**: Actividades y tareas relacionadas con CRM
|
|
116
|
+
**Tabla**: `activities`
|
|
117
|
+
**Campos**:
|
|
118
|
+
- `id` (TEXT/UUID) - Primary key
|
|
119
|
+
- `userId` (TEXT) - User who owns this activity
|
|
120
|
+
- `type` (TEXT) - Activity type (call, email, meeting, task, note)
|
|
121
|
+
- `subject` (TEXT) - Activity subject/title
|
|
122
|
+
- `description` (TEXT) - Detailed description
|
|
123
|
+
- `status` (TEXT) - Status (scheduled, completed, cancelled)
|
|
124
|
+
- `priority` (TEXT) - Priority (low, medium, high, urgent)
|
|
125
|
+
- `dueDate` (TIMESTAMPTZ) - Due date/time
|
|
126
|
+
- `completedAt` (TIMESTAMPTZ) - Completion date/time
|
|
127
|
+
- `duration` (INTEGER) - Duration in minutes
|
|
128
|
+
- `outcome` (TEXT) - Activity outcome/result
|
|
129
|
+
- `location` (TEXT) - Location (for meetings)
|
|
130
|
+
- `entityType` (TEXT) - Related entity type (lead, contact, company, opportunity)
|
|
131
|
+
- `entityId` (TEXT) - Related entity ID
|
|
132
|
+
- `contactId` (TEXT) - Related contact (optional)
|
|
133
|
+
- `companyId` (TEXT) - Related company (optional)
|
|
134
|
+
- `opportunityId` (TEXT) - Related opportunity (optional)
|
|
135
|
+
- `assignedTo` (TEXT) - User ID assigned to
|
|
136
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
137
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
138
|
+
|
|
139
|
+
### 6. CAMPAIGNS
|
|
140
|
+
**Descripción**: Campañas de marketing
|
|
141
|
+
**Tabla**: `campaigns`
|
|
142
|
+
**Campos**:
|
|
143
|
+
- `id` (TEXT/UUID) - Primary key
|
|
144
|
+
- `userId` (TEXT) - User who owns this campaign
|
|
145
|
+
- `name` (TEXT) - Campaign name
|
|
146
|
+
- `type` (TEXT) - Campaign type (email, social, event, webinar, advertising, content)
|
|
147
|
+
- `status` (TEXT) - Status (planned, active, paused, completed, cancelled)
|
|
148
|
+
- `objective` (TEXT) - Campaign objective
|
|
149
|
+
- `description` (TEXT) - Detailed description
|
|
150
|
+
- `startDate` (DATE) - Start date
|
|
151
|
+
- `endDate` (DATE) - End date
|
|
152
|
+
- `budget` (DECIMAL) - Campaign budget
|
|
153
|
+
- `actualCost` (DECIMAL) - Actual cost spent
|
|
154
|
+
- `targetAudience` (TEXT) - Target audience description
|
|
155
|
+
- `targetLeads` (INTEGER) - Target number of leads
|
|
156
|
+
- `actualLeads` (INTEGER) - Actual leads generated
|
|
157
|
+
- `targetRevenue` (DECIMAL) - Target revenue
|
|
158
|
+
- `actualRevenue` (DECIMAL) - Actual revenue generated
|
|
159
|
+
- `roi` (DECIMAL) - Return on investment percentage
|
|
160
|
+
- `channel` (TEXT) - Main channel (email, social_media, web, print, tv, radio)
|
|
161
|
+
- `assignedTo` (TEXT) - User ID of campaign manager
|
|
162
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
163
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
164
|
+
|
|
165
|
+
### 7. NOTES
|
|
166
|
+
**Descripción**: Notas y comentarios
|
|
167
|
+
**Tabla**: `notes`
|
|
168
|
+
**Campos**:
|
|
169
|
+
- `id` (TEXT/UUID) - Primary key
|
|
170
|
+
- `userId` (TEXT) - User who created this note
|
|
171
|
+
- `title` (TEXT) - Note title
|
|
172
|
+
- `content` (TEXT) - Note content
|
|
173
|
+
- `type` (TEXT) - Note type (general, call, meeting, email, followup)
|
|
174
|
+
- `isPinned` (BOOLEAN) - Is pinned/important
|
|
175
|
+
- `isPrivate` (BOOLEAN) - Is private to creator
|
|
176
|
+
- `entityType` (TEXT) - Related entity type (lead, contact, company, opportunity, campaign)
|
|
177
|
+
- `entityId` (TEXT) - Related entity ID
|
|
178
|
+
- `contactId` (TEXT) - Related contact (optional)
|
|
179
|
+
- `companyId` (TEXT) - Related company (optional)
|
|
180
|
+
- `opportunityId` (TEXT) - Related opportunity (optional)
|
|
181
|
+
- `attachments` (JSONB) - Array of attachment URLs
|
|
182
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
183
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
184
|
+
|
|
185
|
+
### 8. PRODUCTS
|
|
186
|
+
**Descripción**: Productos o servicios que se venden
|
|
187
|
+
**Tabla**: `products`
|
|
188
|
+
**Campos**:
|
|
189
|
+
- `id` (TEXT/UUID) - Primary key
|
|
190
|
+
- `userId` (TEXT) - User who owns this product
|
|
191
|
+
- `code` (TEXT) - Product code/SKU
|
|
192
|
+
- `name` (TEXT) - Product name
|
|
193
|
+
- `category` (TEXT) - Product category
|
|
194
|
+
- `type` (TEXT) - Type (product, service, subscription)
|
|
195
|
+
- `description` (TEXT) - Product description
|
|
196
|
+
- `features` (JSONB) - Array of product features
|
|
197
|
+
- `price` (DECIMAL) - Standard price
|
|
198
|
+
- `cost` (DECIMAL) - Product cost
|
|
199
|
+
- `currency` (TEXT) - Currency code
|
|
200
|
+
- `unit` (TEXT) - Unit of measure (piece, hour, month, year)
|
|
201
|
+
- `isActive` (BOOLEAN) - Is currently active
|
|
202
|
+
- `image` (TEXT) - Product image URL
|
|
203
|
+
- `brochureUrl` (TEXT) - Product brochure URL
|
|
204
|
+
- `minimumQuantity` (INTEGER) - Minimum order quantity
|
|
205
|
+
- `commissionRate` (DECIMAL) - Sales commission percentage
|
|
206
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
207
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
208
|
+
|
|
209
|
+
### 9. PIPELINES
|
|
210
|
+
**Descripción**: Pipelines de ventas con sus etapas
|
|
211
|
+
**Tabla**: `pipelines`
|
|
212
|
+
**Campos**:
|
|
213
|
+
- `id` (TEXT/UUID) - Primary key
|
|
214
|
+
- `userId` (TEXT) - User who owns this pipeline
|
|
215
|
+
- `name` (TEXT) - Pipeline name
|
|
216
|
+
- `description` (TEXT) - Pipeline description
|
|
217
|
+
- `type` (TEXT) - Pipeline type (sales, support, project)
|
|
218
|
+
- `isDefault` (BOOLEAN) - Is default pipeline
|
|
219
|
+
- `isActive` (BOOLEAN) - Is currently active
|
|
220
|
+
- `stages` (JSONB) - Array of stages with order, name, probability
|
|
221
|
+
```json
|
|
222
|
+
[
|
|
223
|
+
{"order": 1, "name": "Qualification", "probability": 10, "color": "#3B82F6"},
|
|
224
|
+
{"order": 2, "name": "Needs Analysis", "probability": 25, "color": "#10B981"},
|
|
225
|
+
{"order": 3, "name": "Proposal", "probability": 50, "color": "#F59E0B"},
|
|
226
|
+
{"order": 4, "name": "Negotiation", "probability": 75, "color": "#8B5CF6"},
|
|
227
|
+
{"order": 5, "name": "Closed Won", "probability": 100, "color": "#059669"},
|
|
228
|
+
{"order": 6, "name": "Closed Lost", "probability": 0, "color": "#EF4444"}
|
|
229
|
+
]
|
|
230
|
+
```
|
|
231
|
+
- `dealRottenDays` (INTEGER) - Days until deal is considered rotten
|
|
232
|
+
- `createdAt` (TIMESTAMPTZ)
|
|
233
|
+
- `updatedAt` (TIMESTAMPTZ)
|
|
234
|
+
|
|
235
|
+
## Relaciones entre Entidades
|
|
236
|
+
|
|
237
|
+
### Conversión Lead → Contact/Company
|
|
238
|
+
- `leads.convertedToContactId` → `contacts.id`
|
|
239
|
+
- `leads.convertedToCompanyId` → `companies.id`
|
|
240
|
+
|
|
241
|
+
### Relaciones de Contacts
|
|
242
|
+
- `contacts.companyId` → `companies.id`
|
|
243
|
+
|
|
244
|
+
### Relaciones de Opportunities
|
|
245
|
+
- `opportunities.companyId` → `companies.id`
|
|
246
|
+
- `opportunities.contactId` → `contacts.id`
|
|
247
|
+
- `opportunities.pipelineId` → `pipelines.id`
|
|
248
|
+
|
|
249
|
+
### Relaciones de Activities
|
|
250
|
+
- Polimórfica vía `entityType` y `entityId`
|
|
251
|
+
- Referencias opcionales directas:
|
|
252
|
+
- `activities.contactId` → `contacts.id`
|
|
253
|
+
- `activities.companyId` → `companies.id`
|
|
254
|
+
- `activities.opportunityId` → `opportunities.id`
|
|
255
|
+
|
|
256
|
+
### Relaciones de Notes
|
|
257
|
+
- Polimórfica vía `entityType` y `entityId`
|
|
258
|
+
- Referencias opcionales directas:
|
|
259
|
+
- `notes.contactId` → `contacts.id`
|
|
260
|
+
- `notes.companyId` → `companies.id`
|
|
261
|
+
- `notes.opportunityId` → `opportunities.id`
|
|
262
|
+
|
|
263
|
+
### Relaciones de Campaign
|
|
264
|
+
- Las campañas pueden generar leads
|
|
265
|
+
- Tracking vía activities y notes
|
|
266
|
+
|
|
267
|
+
## Consideraciones de Implementación
|
|
268
|
+
|
|
269
|
+
### Seguridad y Permisos
|
|
270
|
+
- Todas las tablas tienen `userId` para aislamiento multi-tenant
|
|
271
|
+
- RLS (Row Level Security) habilitado en todas las tablas
|
|
272
|
+
- Políticas por rol: admin, sales, marketing, viewer
|
|
273
|
+
|
|
274
|
+
### Metadatos
|
|
275
|
+
- Todas las entidades soportan tabla `{entity}_metas`
|
|
276
|
+
- Estructura estándar: `entityId`, `metaKey`, `metaValue`
|
|
277
|
+
|
|
278
|
+
### Índices Recomendados
|
|
279
|
+
- Por `userId` en todas las tablas
|
|
280
|
+
- Por campos de búsqueda frecuente (email, phone, name)
|
|
281
|
+
- Por foreign keys para JOINs eficientes
|
|
282
|
+
- Por fechas para ordenamiento temporal
|
|
283
|
+
|
|
284
|
+
### Validaciones
|
|
285
|
+
- Emails únicos por usuario en leads y contacts
|
|
286
|
+
- Phone con formato internacional
|
|
287
|
+
- Enums para campos de estado y tipo
|
|
288
|
+
- Probabilidades entre 0-100
|
|
289
|
+
- Montos y costos >= 0
|
|
290
|
+
|
|
291
|
+
## Timeline de Implementación
|
|
292
|
+
|
|
293
|
+
### Fase 1: Estructura Base (Actual)
|
|
294
|
+
1. ✅ Leads (parcialmente creado)
|
|
295
|
+
2. ⏳ Contacts
|
|
296
|
+
3. ⏳ Companies
|
|
297
|
+
4. ⏳ Pipelines
|
|
298
|
+
|
|
299
|
+
### Fase 2: Funcionalidad Core
|
|
300
|
+
5. ⏳ Opportunities
|
|
301
|
+
6. ⏳ Activities
|
|
302
|
+
7. ⏳ Notes
|
|
303
|
+
|
|
304
|
+
### Fase 3: Extensiones
|
|
305
|
+
8. ⏳ Products
|
|
306
|
+
9. ⏳ Campaigns
|
|
307
|
+
|
|
308
|
+
### Fase 4: Sample Data
|
|
309
|
+
- Crear datos relacionados coherentes
|
|
310
|
+
- 10 leads, 5 convertidos a contacts/companies
|
|
311
|
+
- 20 contacts distribuidos en 8 companies
|
|
312
|
+
- 15 opportunities en diferentes stages
|
|
313
|
+
- 50+ activities variadas
|
|
314
|
+
- 5 campaigns con resultados
|
|
315
|
+
- 30+ notes
|
|
316
|
+
- 10 products
|
|
317
|
+
- 2 pipelines (Sales, Support)
|
|
318
|
+
|
|
319
|
+
## Notas de Desarrollo
|
|
320
|
+
|
|
321
|
+
### Convenciones
|
|
322
|
+
- Tablas en plural: `leads`, `contacts`, `companies`
|
|
323
|
+
- Foreign keys genéricas: `entityId` en metas
|
|
324
|
+
- Timestamps: `createdAt`, `updatedAt`
|
|
325
|
+
- IDs como TEXT (UUID convertido)
|
|
326
|
+
- camelCase para campos (compatibilidad con JS/TS)
|
|
327
|
+
|
|
328
|
+
### Performance
|
|
329
|
+
- JSONB para datos estructurados variables (stages, features, attachments)
|
|
330
|
+
- Índices GIN para búsquedas en JSONB
|
|
331
|
+
- Vistas materializadas para dashboards
|
|
332
|
+
- Particionamiento por fecha para activities (futuro)
|
|
333
|
+
|
|
334
|
+
### Integración
|
|
335
|
+
- API REST v1 automática para todas las entidades
|
|
336
|
+
- GraphQL opcional via Hasura
|
|
337
|
+
- Webhooks para eventos importantes
|
|
338
|
+
- Bulk operations para imports/exports
|
|
339
|
+
|
|
340
|
+
## Estado Actual: EN DESARROLLO
|
|
341
|
+
|
|
342
|
+
Creado: 2025-09-27
|
|
343
|
+
Actualizado: 2025-09-27
|
package/about.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# CRM Theme
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Demostrar el modo `single-tenant` donde una empresa tiene un único equipo de trabajo con múltiples usuarios y roles diferenciados para ventas, marketing y gestión.
|
|
6
|
+
|
|
7
|
+
## Producto
|
|
8
|
+
|
|
9
|
+
**SalesForce Pro** - CRM empresarial completo para gestión de ventas, clientes y oportunidades de negocio.
|
|
10
|
+
|
|
11
|
+
## Empresa
|
|
12
|
+
|
|
13
|
+
**Ventas Pro S.A.** - Empresa B2B de servicios tecnológicos que necesita gestionar su pipeline de ventas y relaciones con clientes de forma estructurada.
|
|
14
|
+
|
|
15
|
+
## Teams Mode
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
single-tenant
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- Work team único al registrarse (no personal)
|
|
22
|
+
- Sin team switcher (solo 1 equipo)
|
|
23
|
+
- Invitaciones habilitadas
|
|
24
|
+
- Sin creación de equipos adicionales
|
|
25
|
+
|
|
26
|
+
## Entidades
|
|
27
|
+
|
|
28
|
+
| Entidad | Descripción |
|
|
29
|
+
|---------|-------------|
|
|
30
|
+
| leads | Prospectos y oportunidades iniciales |
|
|
31
|
+
| contacts | Contactos de clientes y empresas |
|
|
32
|
+
| companies | Empresas clientes |
|
|
33
|
+
| opportunities | Oportunidades de venta en pipeline |
|
|
34
|
+
| activities | Llamadas, reuniones, tareas relacionadas |
|
|
35
|
+
| notes | Notas y comentarios sobre entidades |
|
|
36
|
+
| campaigns | Campañas de marketing |
|
|
37
|
+
| pipelines | Configuración de etapas de venta |
|
|
38
|
+
| products | Catálogo de productos/servicios |
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
| Feature | Descripción | Roles |
|
|
43
|
+
|---------|-------------|-------|
|
|
44
|
+
| reports.sales | Ver reportes de ventas | owner, admin |
|
|
45
|
+
| reports.pipeline | Ver reportes de pipeline | owner, admin |
|
|
46
|
+
| reports.marketing | Ver reportes de marketing | owner, admin |
|
|
47
|
+
| leads.convert | Convertir lead a contacto | owner, admin |
|
|
48
|
+
| bulk.import | Importación masiva de datos | owner |
|
|
49
|
+
| bulk.export | Exportación masiva de datos | owner |
|
|
50
|
+
| settings.pipelines | Configurar etapas de pipeline | owner |
|
|
51
|
+
| settings.products | Gestionar catálogo de productos | owner |
|
|
52
|
+
| dashboard.forecasting | Ver pronósticos de ventas | owner, admin |
|
|
53
|
+
|
|
54
|
+
## Permisos Resumidos
|
|
55
|
+
|
|
56
|
+
| Entidad | owner | admin | member |
|
|
57
|
+
|---------|:-----:|:-----:|:------:|
|
|
58
|
+
| leads | CRUD | CRUD | CRU |
|
|
59
|
+
| contacts | CRUD | CRUD | CRU |
|
|
60
|
+
| companies | CRUD | CRUD | R |
|
|
61
|
+
| opportunities | CRUD | CRUD | R |
|
|
62
|
+
| activities | CRUD | CRUD | CRUD |
|
|
63
|
+
| notes | CRUD | CRUD | CRUD |
|
|
64
|
+
| campaigns | CRUD | CRUD | R |
|
|
65
|
+
| pipelines | CRUD | R | R |
|
|
66
|
+
| products | CRUD | R | R |
|
|
67
|
+
|
|
68
|
+
## Usuarios de Prueba
|
|
69
|
+
|
|
70
|
+
| Email | Password | Rol | Descripción |
|
|
71
|
+
|-------|----------|-----|-------------|
|
|
72
|
+
| crm_owner_roberto@nextspark.dev | Test1234 | owner | CEO - Control total |
|
|
73
|
+
| crm_admin_sofia@nextspark.dev | Test1234 | admin | Sales Manager |
|
|
74
|
+
| crm_member_miguel@nextspark.dev | Test1234 | member | Sales Rep |
|
|
75
|
+
| crm_member_laura@nextspark.dev | Test1234 | member | Marketing |
|
|
76
|
+
|
|
77
|
+
## Billing
|
|
78
|
+
|
|
79
|
+
### Modelo de Pricing: Enterprise Tiers
|
|
80
|
+
|
|
81
|
+
> **Los planes y facturas siempre están asociados al team global único. Los tiers se basan en capacidad de usuarios.**
|
|
82
|
+
|
|
83
|
+
### Planes Disponibles
|
|
84
|
+
|
|
85
|
+
| Plan | Mensual | Usuarios Incluidos |
|
|
86
|
+
|------|---------|-------------------|
|
|
87
|
+
| Starter | $299/mes | Hasta 10 |
|
|
88
|
+
| Business | $599/mes | Hasta 50 |
|
|
89
|
+
| Enterprise | $1,499+/mes | Ilimitados |
|
|
90
|
+
|
|
91
|
+
### Características por Plan
|
|
92
|
+
|
|
93
|
+
| Feature | Starter | Business | Enterprise |
|
|
94
|
+
|---------|:-------:|:--------:|:----------:|
|
|
95
|
+
| Leads/Contacts | Ilimitados | Ilimitados | Ilimitados |
|
|
96
|
+
| Pipelines | 2 | 5 | Ilimitados |
|
|
97
|
+
| Productos | 10 | 50 | Ilimitados |
|
|
98
|
+
| Reports | Básicos | Avanzados | Custom |
|
|
99
|
+
| API access | ❌ | ✅ | ✅ |
|
|
100
|
+
| Bulk import/export | ❌ | ✅ | ✅ |
|
|
101
|
+
| SSO/SAML | ❌ | ❌ | ✅ |
|
|
102
|
+
| SLA garantizado | ❌ | ❌ | ✅ |
|
|
103
|
+
| Soporte dedicado | ❌ | ❌ | ✅ |
|
|
104
|
+
|
|
105
|
+
### Facturación
|
|
106
|
+
|
|
107
|
+
- **Unidad de cobro:** Por team global (tiers por capacidad de usuarios)
|
|
108
|
+
- **Ciclos:** Mensual (contratos anuales con descuento disponibles bajo negociación)
|
|
109
|
+
|
|
110
|
+
### Sample Invoices
|
|
111
|
+
|
|
112
|
+
| Team | Plan | Invoices | Status | Total |
|
|
113
|
+
|------|------|----------|--------|-------|
|
|
114
|
+
| Ventas Pro S.A. | Starter | 6 | 5 paid + 1 pending | $1,794 |
|
|
115
|
+
|
|
116
|
+
## Casos de Uso
|
|
117
|
+
|
|
118
|
+
1. CEO revisa pronósticos y configura pipelines
|
|
119
|
+
2. Sales Manager convierte leads y genera reportes
|
|
120
|
+
3. Sales Rep registra actividades y actualiza oportunidades
|
|
121
|
+
4. Marketing gestiona campañas y analiza resultados
|
|
122
|
+
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRM Theme - Application Configuration
|
|
3
|
+
*
|
|
4
|
+
* Single-tenant mode: One organization with multiple teams/departments.
|
|
5
|
+
* Perfect for enterprise sales and marketing operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const APP_CONFIG_OVERRIDES = {
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// APPLICATION METADATA
|
|
11
|
+
// =============================================================================
|
|
12
|
+
app: {
|
|
13
|
+
name: 'CRM Enterprise',
|
|
14
|
+
version: '2.0.0',
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// TEAMS CONFIGURATION - SINGLE-TENANT MODE
|
|
19
|
+
// =============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Single-tenant mode:
|
|
22
|
+
* - One work team created at signup (no personal team)
|
|
23
|
+
* - Owner can invite members with different roles
|
|
24
|
+
* - No team switching (only one organization)
|
|
25
|
+
* - Multi-department structure via roles
|
|
26
|
+
*/
|
|
27
|
+
teams: {
|
|
28
|
+
mode: 'single-tenant' as const,
|
|
29
|
+
options: {
|
|
30
|
+
maxMembersPerTeam: 50,
|
|
31
|
+
allowLeaveTeam: false, // Controlled by admin
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// INTERNATIONALIZATION
|
|
37
|
+
// =============================================================================
|
|
38
|
+
i18n: {
|
|
39
|
+
supportedLocales: ['en', 'es'],
|
|
40
|
+
defaultLocale: 'en' as const,
|
|
41
|
+
namespaces: [
|
|
42
|
+
'common',
|
|
43
|
+
'dashboard',
|
|
44
|
+
'settings',
|
|
45
|
+
'auth',
|
|
46
|
+
'validation',
|
|
47
|
+
// CRM entities
|
|
48
|
+
'leads',
|
|
49
|
+
'contacts',
|
|
50
|
+
'companies',
|
|
51
|
+
'opportunities',
|
|
52
|
+
'activities',
|
|
53
|
+
'campaigns',
|
|
54
|
+
'notes',
|
|
55
|
+
'products',
|
|
56
|
+
'pipelines',
|
|
57
|
+
// Theme specific
|
|
58
|
+
'crm',
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// API CONFIGURATION
|
|
64
|
+
// =============================================================================
|
|
65
|
+
api: {
|
|
66
|
+
cors: {
|
|
67
|
+
allowedOrigins: {
|
|
68
|
+
development: [
|
|
69
|
+
'http://localhost:3000',
|
|
70
|
+
'http://localhost:5173',
|
|
71
|
+
],
|
|
72
|
+
production: [],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// =============================================================================
|
|
78
|
+
// DOCUMENTATION
|
|
79
|
+
// =============================================================================
|
|
80
|
+
docs: {
|
|
81
|
+
enabled: true,
|
|
82
|
+
public: false,
|
|
83
|
+
searchEnabled: true,
|
|
84
|
+
breadcrumbs: true,
|
|
85
|
+
theme: {
|
|
86
|
+
enabled: true,
|
|
87
|
+
open: true,
|
|
88
|
+
label: "CRM Theme",
|
|
89
|
+
},
|
|
90
|
+
plugins: {
|
|
91
|
+
enabled: false,
|
|
92
|
+
open: false,
|
|
93
|
+
label: "Plugins",
|
|
94
|
+
},
|
|
95
|
+
core: {
|
|
96
|
+
enabled: true,
|
|
97
|
+
open: false,
|
|
98
|
+
label: "Core",
|
|
99
|
+
},
|
|
100
|
+
showPluginsDocsInProd: false,
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// =============================================================================
|
|
104
|
+
// SCHEDULED ACTIONS (CRM needs more history and higher throughput)
|
|
105
|
+
// =============================================================================
|
|
106
|
+
scheduledActions: {
|
|
107
|
+
enabled: true,
|
|
108
|
+
retentionDays: 14, // CRM needs more history for auditing
|
|
109
|
+
batchSize: 20, // CRM has more scheduled actions
|
|
110
|
+
defaultTimeout: 45000, // Longer timeout for CRM integrations
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// MOBILE NAVIGATION
|
|
115
|
+
// =============================================================================
|
|
116
|
+
mobileNav: {
|
|
117
|
+
items: [
|
|
118
|
+
{
|
|
119
|
+
id: 'home',
|
|
120
|
+
labelKey: 'common.mobileNav.home',
|
|
121
|
+
href: '/dashboard',
|
|
122
|
+
icon: 'Home',
|
|
123
|
+
enabled: true,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'leads',
|
|
127
|
+
labelKey: 'crm.navigation.leads',
|
|
128
|
+
href: '/dashboard/leads',
|
|
129
|
+
icon: 'UserSearch',
|
|
130
|
+
enabled: true,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 'create',
|
|
134
|
+
labelKey: 'common.mobileNav.create',
|
|
135
|
+
icon: 'Plus',
|
|
136
|
+
isCentral: true,
|
|
137
|
+
action: 'quickCreate',
|
|
138
|
+
enabled: true,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'opportunities',
|
|
142
|
+
labelKey: 'crm.navigation.opportunities',
|
|
143
|
+
href: '/dashboard/opportunities',
|
|
144
|
+
icon: 'TrendingUp',
|
|
145
|
+
enabled: true,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'settings',
|
|
149
|
+
labelKey: 'common.mobileNav.settings',
|
|
150
|
+
href: '/dashboard/settings',
|
|
151
|
+
icon: 'Settings',
|
|
152
|
+
enabled: true,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
moreSheetItems: [
|
|
156
|
+
{
|
|
157
|
+
id: 'contacts',
|
|
158
|
+
labelKey: 'crm.navigation.contacts',
|
|
159
|
+
href: '/dashboard/contacts',
|
|
160
|
+
icon: 'Users',
|
|
161
|
+
enabled: true,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'companies',
|
|
165
|
+
labelKey: 'crm.navigation.companies',
|
|
166
|
+
href: '/dashboard/companies',
|
|
167
|
+
icon: 'Building2',
|
|
168
|
+
enabled: true,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'activities',
|
|
172
|
+
labelKey: 'crm.navigation.activities',
|
|
173
|
+
href: '/dashboard/activities',
|
|
174
|
+
icon: 'Calendar',
|
|
175
|
+
enabled: true,
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// =============================================================================
|
|
181
|
+
// DEV KEYRING - MOVED TO dev.config.ts
|
|
182
|
+
// =============================================================================
|
|
183
|
+
// DevKeyring configuration has been moved to config/dev.config.ts
|
|
184
|
+
// This separates development-only settings from production configuration.
|
|
185
|
+
}
|