constec 0.7.1__py3-none-any.whl

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 (40) hide show
  1. constec/db/__init__.py +11 -0
  2. constec/db/apps.py +8 -0
  3. constec/db/migrations/0001_initial.py +551 -0
  4. constec/db/migrations/0002_module_level.py +38 -0
  5. constec/db/migrations/0003_remove_module_level.py +15 -0
  6. constec/db/migrations/0004_rename_entities_company_cuit_idx_entities_company_e2c50f_idx_and_more.py +345 -0
  7. constec/db/migrations/0005_event.py +46 -0
  8. constec/db/migrations/0006_automation_trigger_action_executionlog_notificationtemplate.py +275 -0
  9. constec/db/migrations/0007_add_organization_to_automations.py +91 -0
  10. constec/db/migrations/0008_refactor_creator_fields.py +173 -0
  11. constec/db/migrations/0009_rename_user_to_companyuser.py +40 -0
  12. constec/db/migrations/__init__.py +0 -0
  13. constec/db/models/__init__.py +110 -0
  14. constec/db/models/automation.py +488 -0
  15. constec/db/models/base.py +23 -0
  16. constec/db/models/company.py +36 -0
  17. constec/db/models/contact.py +71 -0
  18. constec/db/models/erp.py +101 -0
  19. constec/db/models/erp_entity.py +122 -0
  20. constec/db/models/flow.py +138 -0
  21. constec/db/models/group.py +36 -0
  22. constec/db/models/module.py +67 -0
  23. constec/db/models/organization.py +62 -0
  24. constec/db/models/person.py +28 -0
  25. constec/db/models/session.py +89 -0
  26. constec/db/models/tag.py +70 -0
  27. constec/db/models/user.py +74 -0
  28. constec/py.typed +0 -0
  29. constec/services/__init__.py +14 -0
  30. constec/services/encryption.py +92 -0
  31. constec/shared/__init__.py +20 -0
  32. constec/shared/exceptions.py +48 -0
  33. constec/utils/__init__.py +20 -0
  34. constec/utils/cuit.py +107 -0
  35. constec/utils/password.py +62 -0
  36. constec-0.7.1.dist-info/METADATA +94 -0
  37. constec-0.7.1.dist-info/RECORD +40 -0
  38. constec-0.7.1.dist-info/WHEEL +5 -0
  39. constec-0.7.1.dist-info/licenses/LICENSE +21 -0
  40. constec-0.7.1.dist-info/top_level.txt +1 -0
constec/db/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """
2
+ constec.db - Django models for the Constec platform.
3
+
4
+ This package provides centralized model definitions shared between
5
+ constec-core-api and constancia-api.
6
+
7
+ Usage:
8
+ from constec.db.models import Company, User, Session
9
+ """
10
+
11
+ default_app_config = 'constec.db.apps.ConstecDbConfig'
constec/db/apps.py ADDED
@@ -0,0 +1,8 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class ConstecDbConfig(AppConfig):
5
+ default_auto_field = 'django.db.models.BigAutoField'
6
+ name = 'constec.db'
7
+ label = 'constec_db'
8
+ verbose_name = 'Constec Database Models'
@@ -0,0 +1,551 @@
1
+ # Generated by Django 6.0.1 on 2026-01-26 20:41
2
+
3
+ import django.db.models.deletion
4
+ import uuid
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ initial = True
11
+
12
+ dependencies = [
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='ContactType',
18
+ fields=[
19
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
20
+ ('name', models.CharField(max_length=50)),
21
+ ('description', models.TextField(blank=True, null=True)),
22
+ ],
23
+ options={
24
+ 'db_table': 'core"."contact_types',
25
+ },
26
+ ),
27
+ migrations.CreateModel(
28
+ name='Entity',
29
+ fields=[
30
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
31
+ ('external_id', models.CharField(help_text='Entity ID in external ERP system (e.g., cli_Cod, pro_Cod)', max_length=255)),
32
+ ('cuit', models.CharField(blank=True, default='', help_text='CUIT without dashes (for authentication lookup)', max_length=13)),
33
+ ('metadata', models.JSONField(blank=True, default=dict)),
34
+ ],
35
+ options={
36
+ 'db_table': 'erp"."entities',
37
+ 'verbose_name_plural': 'Entities',
38
+ },
39
+ ),
40
+ migrations.CreateModel(
41
+ name='FlowTemplate',
42
+ fields=[
43
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
44
+ ('name', models.CharField(max_length=100)),
45
+ ('description', models.TextField()),
46
+ ('category', models.CharField(choices=[('finance', 'Finance & Accounting'), ('customer_service', 'Customer Service'), ('sales', 'Sales & CRM'), ('general', 'General Purpose'), ('custom', 'Custom')], max_length=50)),
47
+ ('graph_definition', models.JSONField(help_text='Graph structure in JSON format with nodes and edges')),
48
+ ('default_config', models.JSONField(default=dict, help_text='Default configuration for this template (LLM, tools, prompts)')),
49
+ ('is_global', models.BooleanField(default=False, help_text='If true, all organizations can use this template')),
50
+ ('is_active', models.BooleanField(default=True)),
51
+ ('version', models.CharField(default='1.0.0', max_length=20)),
52
+ ('created_at', models.DateTimeField(auto_now_add=True)),
53
+ ('updated_at', models.DateTimeField(auto_now=True)),
54
+ ],
55
+ options={
56
+ 'db_table': 'constancia"."flow_templates',
57
+ },
58
+ ),
59
+ migrations.CreateModel(
60
+ name='Module',
61
+ fields=[
62
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
63
+ ('name', models.CharField(max_length=100)),
64
+ ('slug', models.SlugField(max_length=100, null=True)),
65
+ ('description', models.TextField(blank=True, null=True)),
66
+ ('version', models.CharField(max_length=20)),
67
+ ('is_active', models.BooleanField(default=True)),
68
+ ],
69
+ options={
70
+ 'db_table': 'core"."modules',
71
+ },
72
+ ),
73
+ migrations.CreateModel(
74
+ name='Organization',
75
+ fields=[
76
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
77
+ ('name', models.CharField(max_length=255)),
78
+ ('slug', models.SlugField(max_length=100, unique=True)),
79
+ ('description', models.TextField(blank=True, null=True)),
80
+ ],
81
+ options={
82
+ 'db_table': 'core"."organizations',
83
+ },
84
+ ),
85
+ migrations.CreateModel(
86
+ name='Role',
87
+ fields=[
88
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
89
+ ('name', models.CharField(max_length=100)),
90
+ ('description', models.TextField(blank=True, null=True)),
91
+ ],
92
+ options={
93
+ 'db_table': 'erp"."roles',
94
+ },
95
+ ),
96
+ migrations.CreateModel(
97
+ name='System',
98
+ fields=[
99
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
100
+ ('name', models.CharField(max_length=100, unique=True)),
101
+ ('description', models.TextField(blank=True, null=True)),
102
+ ('api_endpoint', models.URLField(blank=True)),
103
+ ('metadata', models.JSONField(blank=True, default=dict)),
104
+ ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
105
+ ('updated_at', models.DateTimeField(auto_now=True, null=True)),
106
+ ],
107
+ options={
108
+ 'db_table': 'erp"."systems',
109
+ },
110
+ ),
111
+ migrations.CreateModel(
112
+ name='Company',
113
+ fields=[
114
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
115
+ ('name', models.CharField(max_length=255)),
116
+ ('legal_name', models.CharField(max_length=255)),
117
+ ('slug', models.SlugField(max_length=100, unique=True)),
118
+ ('website', models.URLField(blank=True, null=True)),
119
+ ('is_active', models.BooleanField(default=True)),
120
+ ('parent_company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='constec_db.company')),
121
+ ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='companies', to='constec_db.organization')),
122
+ ],
123
+ options={
124
+ 'db_table': 'core"."companies',
125
+ 'verbose_name_plural': 'Companies',
126
+ },
127
+ ),
128
+ migrations.CreateModel(
129
+ name='Contact',
130
+ fields=[
131
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
132
+ ('label', models.CharField(blank=True, help_text="Optional label (e.g. 'Personal', 'Work')", max_length=100)),
133
+ ('value', models.CharField(max_length=255)),
134
+ ('metadata', models.JSONField(blank=True, default=dict)),
135
+ ('type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contacts', to='constec_db.contacttype')),
136
+ ],
137
+ options={
138
+ 'db_table': 'core"."contacts',
139
+ },
140
+ ),
141
+ migrations.CreateModel(
142
+ name='EntityAuth',
143
+ fields=[
144
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
145
+ ('password_hash', models.CharField(help_text='Bcrypt hashed password', max_length=255)),
146
+ ('is_active', models.BooleanField(default=True, help_text='Whether this account can authenticate')),
147
+ ('created_at', models.DateTimeField(auto_now_add=True)),
148
+ ('updated_at', models.DateTimeField(auto_now=True)),
149
+ ('last_login', models.DateTimeField(blank=True, help_text='Last successful login timestamp', null=True)),
150
+ ('entity', models.OneToOneField(help_text='The ERP entity these credentials belong to', on_delete=django.db.models.deletion.CASCADE, related_name='auth', to='constec_db.entity')),
151
+ ],
152
+ options={
153
+ 'verbose_name': 'Entity Authentication',
154
+ 'verbose_name_plural': 'Entity Authentications',
155
+ 'db_table': 'erp"."entity_auth',
156
+ },
157
+ ),
158
+ migrations.CreateModel(
159
+ name='Flow',
160
+ fields=[
161
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
162
+ ('name', models.CharField(max_length=100)),
163
+ ('description', models.TextField(blank=True, null=True)),
164
+ ('graph_definition', models.JSONField(blank=True, help_text='Custom graph structure (only if not using template)', null=True)),
165
+ ('config', models.JSONField(default=dict, help_text='Configuration that merges with template.default_config')),
166
+ ('is_active', models.BooleanField(default=True)),
167
+ ('is_default', models.BooleanField(default=False, help_text='Whether this is the default flow for the company')),
168
+ ('created_at', models.DateTimeField(auto_now_add=True)),
169
+ ('updated_at', models.DateTimeField(auto_now=True)),
170
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='flows', to='constec_db.company')),
171
+ ('template', models.ForeignKey(blank=True, help_text="If set, uses template's graph. config overrides template defaults.", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='flows', to='constec_db.flowtemplate')),
172
+ ],
173
+ options={
174
+ 'db_table': 'constancia"."flows',
175
+ },
176
+ ),
177
+ migrations.CreateModel(
178
+ name='CompanyModule',
179
+ fields=[
180
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
181
+ ('is_enabled', models.BooleanField(default=True)),
182
+ ('settings', models.JSONField(blank=True, default=dict)),
183
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='company_modules', to='constec_db.company')),
184
+ ('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='company_modules', to='constec_db.module')),
185
+ ],
186
+ options={
187
+ 'db_table': 'core"."company_modules',
188
+ },
189
+ ),
190
+ migrations.AddField(
191
+ model_name='flowtemplate',
192
+ name='organization',
193
+ field=models.ForeignKey(blank=True, help_text='Organization that owns this template (null for global)', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='flow_templates', to='constec_db.organization'),
194
+ ),
195
+ migrations.CreateModel(
196
+ name='OrganizationRole',
197
+ fields=[
198
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
199
+ ('name', models.CharField(max_length=100)),
200
+ ('description', models.TextField(blank=True, null=True)),
201
+ ('permissions', models.JSONField(default=dict)),
202
+ ('is_system_role', models.BooleanField(default=False)),
203
+ ('organization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_roles', to='constec_db.organization')),
204
+ ],
205
+ options={
206
+ 'db_table': 'core"."organization_roles',
207
+ },
208
+ ),
209
+ migrations.CreateModel(
210
+ name='OrganizationUser',
211
+ fields=[
212
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
213
+ ('name', models.CharField(max_length=255)),
214
+ ('email', models.EmailField(max_length=254, unique=True)),
215
+ ('password_hash', models.CharField(max_length=255)),
216
+ ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='users', to='constec_db.organization')),
217
+ ('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='constec_db.organizationrole')),
218
+ ],
219
+ options={
220
+ 'db_table': 'core"."organization_users',
221
+ },
222
+ ),
223
+ migrations.AddField(
224
+ model_name='flowtemplate',
225
+ name='created_by',
226
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_templates', to='constec_db.organizationuser'),
227
+ ),
228
+ migrations.CreateModel(
229
+ name='Person',
230
+ fields=[
231
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
232
+ ('first_name', models.CharField(max_length=100)),
233
+ ('last_name', models.CharField(max_length=100)),
234
+ ('full_name', models.CharField(max_length=255)),
235
+ ('metadata', models.JSONField(blank=True, default=dict)),
236
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='persons', to='constec_db.company')),
237
+ ],
238
+ options={
239
+ 'db_table': 'core"."persons',
240
+ },
241
+ ),
242
+ migrations.AddField(
243
+ model_name='entity',
244
+ name='company',
245
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='erp_entities', to='constec_db.company'),
246
+ ),
247
+ migrations.AddField(
248
+ model_name='entity',
249
+ name='person',
250
+ field=models.ForeignKey(blank=True, help_text='Optional link to Core person', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='erp_entities', to='constec_db.person'),
251
+ ),
252
+ migrations.CreateModel(
253
+ name='PersonContact',
254
+ fields=[
255
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
256
+ ('is_primary', models.BooleanField(default=False)),
257
+ ('contact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_contacts', to='constec_db.contact')),
258
+ ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_contacts', to='constec_db.person')),
259
+ ],
260
+ options={
261
+ 'db_table': 'core"."person_contacts',
262
+ },
263
+ ),
264
+ migrations.CreateModel(
265
+ name='PersonTag',
266
+ fields=[
267
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
268
+ ('name', models.CharField(max_length=50)),
269
+ ('color', models.CharField(blank=True, max_length=7, null=True)),
270
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_tags', to='constec_db.company')),
271
+ ],
272
+ options={
273
+ 'db_table': 'core"."person_tags',
274
+ },
275
+ ),
276
+ migrations.CreateModel(
277
+ name='PersonTagged',
278
+ fields=[
279
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
280
+ ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='constec_db.person')),
281
+ ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_persons', to='constec_db.persontag')),
282
+ ],
283
+ options={
284
+ 'db_table': 'core"."person_tagged',
285
+ },
286
+ ),
287
+ migrations.AddField(
288
+ model_name='entity',
289
+ name='role',
290
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='entities', to='constec_db.role'),
291
+ ),
292
+ migrations.CreateModel(
293
+ name='Session',
294
+ fields=[
295
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
296
+ ('metadata', models.JSONField(default=dict, help_text='Session context (connection, role, etc.)')),
297
+ ('is_active', models.BooleanField(default=True)),
298
+ ('ended_at', models.DateTimeField(blank=True, null=True)),
299
+ ('created_at', models.DateTimeField(auto_now_add=True)),
300
+ ('updated_at', models.DateTimeField(auto_now=True)),
301
+ ('company', models.ForeignKey(help_text='The company this session belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to='constec_db.company')),
302
+ ('flow', models.ForeignKey(help_text='AI flow configuration to use', on_delete=django.db.models.deletion.PROTECT, related_name='sessions', to='constec_db.flow')),
303
+ ('user', models.ForeignKey(help_text='The person chatting (can be employee or client)', on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to='constec_db.person')),
304
+ ],
305
+ options={
306
+ 'db_table': 'constancia"."sessions',
307
+ },
308
+ ),
309
+ migrations.CreateModel(
310
+ name='Message',
311
+ fields=[
312
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
313
+ ('role', models.CharField(choices=[('user', 'User'), ('assistant', 'Assistant')], max_length=20)),
314
+ ('content', models.TextField()),
315
+ ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional message data: tool calls, errors, context, etc.')),
316
+ ('created_at', models.DateTimeField(auto_now_add=True)),
317
+ ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='constec_db.session')),
318
+ ],
319
+ options={
320
+ 'db_table': 'constancia"."messages',
321
+ 'ordering': ['created_at'],
322
+ },
323
+ ),
324
+ migrations.AddField(
325
+ model_name='role',
326
+ name='system',
327
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='constec_db.system'),
328
+ ),
329
+ migrations.AddField(
330
+ model_name='entity',
331
+ name='system',
332
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='entities', to='constec_db.system'),
333
+ ),
334
+ migrations.CreateModel(
335
+ name='Connection',
336
+ fields=[
337
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
338
+ ('name', models.CharField(blank=True, default='', help_text='Descriptive name for this connection', max_length=100)),
339
+ ('slug', models.CharField(max_length=50)),
340
+ ('db_type', models.CharField(choices=[('mssql', 'SQL Server'), ('postgresql', 'PostgreSQL'), ('mysql', 'MySQL')], default='mssql', max_length=20)),
341
+ ('host', models.CharField(max_length=255)),
342
+ ('port', models.IntegerField()),
343
+ ('database', models.CharField(max_length=100)),
344
+ ('username', models.CharField(max_length=100)),
345
+ ('encrypted_password', models.TextField()),
346
+ ('is_active', models.BooleanField(default=True)),
347
+ ('last_tested_at', models.DateTimeField(blank=True, null=True)),
348
+ ('created_at', models.DateTimeField(auto_now_add=True)),
349
+ ('updated_at', models.DateTimeField(auto_now=True)),
350
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='erp_connections', to='constec_db.company')),
351
+ ('system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='connections', to='constec_db.system')),
352
+ ],
353
+ options={
354
+ 'db_table': 'erp"."connections',
355
+ },
356
+ ),
357
+ migrations.CreateModel(
358
+ name='CompanySystem',
359
+ fields=[
360
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
361
+ ('is_primary', models.BooleanField(default=False, help_text='Whether this is the primary ERP system for the company')),
362
+ ('is_active', models.BooleanField(default=True)),
363
+ ('metadata', models.JSONField(blank=True, default=dict)),
364
+ ('created_at', models.DateTimeField(auto_now_add=True)),
365
+ ('updated_at', models.DateTimeField(auto_now=True)),
366
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='erp_systems', to='constec_db.company')),
367
+ ('system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='company_assignments', to='constec_db.system')),
368
+ ],
369
+ options={
370
+ 'db_table': 'erp"."company_systems',
371
+ },
372
+ ),
373
+ migrations.CreateModel(
374
+ name='TagCategory',
375
+ fields=[
376
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
377
+ ('name', models.CharField(max_length=50)),
378
+ ('description', models.TextField(blank=True, null=True)),
379
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tag_categories', to='constec_db.company')),
380
+ ],
381
+ options={
382
+ 'db_table': 'core"."tag_categories',
383
+ 'verbose_name': 'Tag category',
384
+ 'verbose_name_plural': 'Tag categories',
385
+ },
386
+ ),
387
+ migrations.AddField(
388
+ model_name='persontag',
389
+ name='category',
390
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_tags', to='constec_db.tagcategory'),
391
+ ),
392
+ migrations.CreateModel(
393
+ name='User',
394
+ fields=[
395
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
396
+ ('name', models.CharField(max_length=255)),
397
+ ('email', models.EmailField(max_length=254, unique=True)),
398
+ ('password_hash', models.CharField(max_length=255)),
399
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='users', to='constec_db.company')),
400
+ ],
401
+ options={
402
+ 'db_table': 'core"."users',
403
+ },
404
+ ),
405
+ migrations.CreateModel(
406
+ name='UserGroup',
407
+ fields=[
408
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
409
+ ('name', models.CharField(max_length=100)),
410
+ ('description', models.TextField(blank=True, null=True)),
411
+ ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_groups', to='constec_db.company')),
412
+ ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sub_groups', to='constec_db.usergroup')),
413
+ ('users', models.ManyToManyField(related_name='groups', to='constec_db.user')),
414
+ ],
415
+ options={
416
+ 'db_table': 'core"."user_groups',
417
+ },
418
+ ),
419
+ migrations.CreateModel(
420
+ name='UserRole',
421
+ fields=[
422
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
423
+ ('name', models.CharField(max_length=100)),
424
+ ('description', models.TextField(blank=True, null=True)),
425
+ ('permissions', models.JSONField(default=dict)),
426
+ ('is_system_role', models.BooleanField(default=False)),
427
+ ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to='constec_db.company')),
428
+ ],
429
+ options={
430
+ 'db_table': 'core"."user_roles',
431
+ },
432
+ ),
433
+ migrations.CreateModel(
434
+ name='UserCompanyAccess',
435
+ fields=[
436
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
437
+ ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_accesses', to='constec_db.company')),
438
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='company_accesses', to='constec_db.user')),
439
+ ('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='user_accesses', to='constec_db.userrole')),
440
+ ],
441
+ options={
442
+ 'db_table': 'core"."user_company_access',
443
+ 'verbose_name': 'User company access',
444
+ 'verbose_name_plural': 'User company access',
445
+ },
446
+ ),
447
+ migrations.AddIndex(
448
+ model_name='flow',
449
+ index=models.Index(fields=['company', 'is_default'], name='flows_company_982968_idx'),
450
+ ),
451
+ migrations.AddIndex(
452
+ model_name='flow',
453
+ index=models.Index(fields=['template', 'is_active'], name='flows_templat_638f1d_idx'),
454
+ ),
455
+ migrations.AlterUniqueTogether(
456
+ name='flow',
457
+ unique_together={('company', 'name')},
458
+ ),
459
+ migrations.AlterUniqueTogether(
460
+ name='companymodule',
461
+ unique_together={('company', 'module')},
462
+ ),
463
+ migrations.AlterUniqueTogether(
464
+ name='organizationrole',
465
+ unique_together={('organization', 'name')},
466
+ ),
467
+ migrations.AddIndex(
468
+ model_name='flowtemplate',
469
+ index=models.Index(fields=['organization', 'is_global'], name='flow_templa_organiz_abebc3_idx'),
470
+ ),
471
+ migrations.AddIndex(
472
+ model_name='flowtemplate',
473
+ index=models.Index(fields=['category', 'is_active'], name='flow_templa_categor_976487_idx'),
474
+ ),
475
+ migrations.AlterUniqueTogether(
476
+ name='flowtemplate',
477
+ unique_together={('organization', 'name', 'version')},
478
+ ),
479
+ migrations.AlterUniqueTogether(
480
+ name='personcontact',
481
+ unique_together={('person', 'contact')},
482
+ ),
483
+ migrations.AlterUniqueTogether(
484
+ name='persontagged',
485
+ unique_together={('person', 'tag')},
486
+ ),
487
+ migrations.AddIndex(
488
+ model_name='session',
489
+ index=models.Index(fields=['company', 'is_active'], name='sessions_company_30036a_idx'),
490
+ ),
491
+ migrations.AddIndex(
492
+ model_name='session',
493
+ index=models.Index(fields=['user', 'is_active'], name='sessions_user_id_85103c_idx'),
494
+ ),
495
+ migrations.AddIndex(
496
+ model_name='session',
497
+ index=models.Index(fields=['-created_at'], name='sessions_created_eb29b2_idx'),
498
+ ),
499
+ migrations.AddIndex(
500
+ model_name='message',
501
+ index=models.Index(fields=['session', 'created_at'], name='messages_session_1b3070_idx'),
502
+ ),
503
+ migrations.AlterUniqueTogether(
504
+ name='role',
505
+ unique_together={('system', 'name')},
506
+ ),
507
+ migrations.AddIndex(
508
+ model_name='entity',
509
+ index=models.Index(fields=['cuit'], name='entities_cuit_ad5bc3_idx'),
510
+ ),
511
+ migrations.AddIndex(
512
+ model_name='entity',
513
+ index=models.Index(fields=['company', 'cuit'], name='entities_company_cuit_idx'),
514
+ ),
515
+ migrations.AlterUniqueTogether(
516
+ name='entity',
517
+ unique_together={('company', 'role', 'external_id')},
518
+ ),
519
+ migrations.AlterUniqueTogether(
520
+ name='connection',
521
+ unique_together={('system', 'slug')},
522
+ ),
523
+ migrations.AddIndex(
524
+ model_name='companysystem',
525
+ index=models.Index(fields=['company', 'is_primary'], name='company_sys_company_e5ff34_idx'),
526
+ ),
527
+ migrations.AddIndex(
528
+ model_name='companysystem',
529
+ index=models.Index(fields=['system', 'is_active'], name='company_sys_system__aeef9f_idx'),
530
+ ),
531
+ migrations.AlterUniqueTogether(
532
+ name='companysystem',
533
+ unique_together={('company', 'system')},
534
+ ),
535
+ migrations.AlterUniqueTogether(
536
+ name='persontag',
537
+ unique_together={('company', 'category', 'name')},
538
+ ),
539
+ migrations.AlterUniqueTogether(
540
+ name='usergroup',
541
+ unique_together={('company', 'name')},
542
+ ),
543
+ migrations.AlterUniqueTogether(
544
+ name='userrole',
545
+ unique_together={('company', 'name')},
546
+ ),
547
+ migrations.AlterUniqueTogether(
548
+ name='usercompanyaccess',
549
+ unique_together={('user', 'company')},
550
+ ),
551
+ ]
@@ -0,0 +1,38 @@
1
+ from django.db import migrations, models
2
+ import django.db.models.deletion
3
+ import uuid
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('constec_db', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='module',
15
+ name='level',
16
+ field=models.CharField(
17
+ choices=[('organization', 'Organization Level'), ('company', 'Company Level')],
18
+ default='company',
19
+ max_length=20,
20
+ ),
21
+ ),
22
+ migrations.CreateModel(
23
+ name='OrganizationModule',
24
+ fields=[
25
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
26
+ ('created_at', models.DateTimeField(auto_now_add=True)),
27
+ ('updated_at', models.DateTimeField(auto_now=True)),
28
+ ('is_enabled', models.BooleanField(default=True)),
29
+ ('settings', models.JSONField(blank=True, default=dict)),
30
+ ('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organization_modules', to='constec_db.module')),
31
+ ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organization_modules', to='constec_db.organization')),
32
+ ],
33
+ options={
34
+ 'db_table': 'core"."organization_modules',
35
+ 'unique_together': {('organization', 'module')},
36
+ },
37
+ ),
38
+ ]
@@ -0,0 +1,15 @@
1
+ from django.db import migrations
2
+
3
+
4
+ class Migration(migrations.Migration):
5
+
6
+ dependencies = [
7
+ ('constec_db', '0002_module_level'),
8
+ ]
9
+
10
+ operations = [
11
+ migrations.RemoveField(
12
+ model_name='module',
13
+ name='level',
14
+ ),
15
+ ]