constec 0.3.4__tar.gz → 0.4.1__tar.gz
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.
- {constec-0.3.4 → constec-0.4.1}/PKG-INFO +1 -1
- constec-0.4.1/constec/db/migrations/0004_rename_entities_company_cuit_idx_entities_company_e2c50f_idx_and_more.py +345 -0
- constec-0.4.1/constec/db/migrations/0005_event.py +46 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/__init__.py +5 -0
- constec-0.4.1/constec/db/models/automation.py +99 -0
- constec-0.4.1/constec/db/models/base.py +23 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/company.py +0 -1
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/erp.py +3 -11
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/erp_entity.py +3 -9
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/flow.py +0 -7
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/module.py +0 -1
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/session.py +0 -5
- {constec-0.3.4 → constec-0.4.1}/constec.egg-info/PKG-INFO +1 -1
- {constec-0.3.4 → constec-0.4.1}/constec.egg-info/SOURCES.txt +3 -0
- {constec-0.3.4 → constec-0.4.1}/pyproject.toml +1 -1
- constec-0.3.4/constec/db/models/base.py +0 -14
- {constec-0.3.4 → constec-0.4.1}/LICENSE +0 -0
- {constec-0.3.4 → constec-0.4.1}/README.md +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/__init__.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/apps.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/migrations/0001_initial.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/migrations/0002_module_level.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/migrations/0003_remove_module_level.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/migrations/__init__.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/contact.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/group.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/organization.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/person.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/tag.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/db/models/user.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/py.typed +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/services/__init__.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/services/encryption.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/shared/__init__.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/shared/exceptions.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/utils/__init__.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/utils/cuit.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec/utils/password.py +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec.egg-info/dependency_links.txt +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec.egg-info/requires.txt +0 -0
- {constec-0.3.4 → constec-0.4.1}/constec.egg-info/top_level.txt +0 -0
- {constec-0.3.4 → constec-0.4.1}/setup.cfg +0 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Generated by Django 6.0.1 on 2026-01-29 13:27
|
|
2
|
+
|
|
3
|
+
import django.utils.timezone
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('constec_db', '0003_remove_module_level'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='company',
|
|
16
|
+
name='created_at',
|
|
17
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
18
|
+
preserve_default=False,
|
|
19
|
+
),
|
|
20
|
+
migrations.AddField(
|
|
21
|
+
model_name='company',
|
|
22
|
+
name='updated_at',
|
|
23
|
+
field=models.DateTimeField(auto_now=True),
|
|
24
|
+
),
|
|
25
|
+
migrations.AddField(
|
|
26
|
+
model_name='companymodule',
|
|
27
|
+
name='created_at',
|
|
28
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
29
|
+
preserve_default=False,
|
|
30
|
+
),
|
|
31
|
+
migrations.AddField(
|
|
32
|
+
model_name='companymodule',
|
|
33
|
+
name='is_active',
|
|
34
|
+
field=models.BooleanField(default=True),
|
|
35
|
+
),
|
|
36
|
+
migrations.AddField(
|
|
37
|
+
model_name='companymodule',
|
|
38
|
+
name='updated_at',
|
|
39
|
+
field=models.DateTimeField(auto_now=True),
|
|
40
|
+
),
|
|
41
|
+
migrations.AddField(
|
|
42
|
+
model_name='contact',
|
|
43
|
+
name='created_at',
|
|
44
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
45
|
+
preserve_default=False,
|
|
46
|
+
),
|
|
47
|
+
migrations.AddField(
|
|
48
|
+
model_name='contact',
|
|
49
|
+
name='is_active',
|
|
50
|
+
field=models.BooleanField(default=True),
|
|
51
|
+
),
|
|
52
|
+
migrations.AddField(
|
|
53
|
+
model_name='contact',
|
|
54
|
+
name='updated_at',
|
|
55
|
+
field=models.DateTimeField(auto_now=True),
|
|
56
|
+
),
|
|
57
|
+
migrations.AddField(
|
|
58
|
+
model_name='contacttype',
|
|
59
|
+
name='created_at',
|
|
60
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
61
|
+
preserve_default=False,
|
|
62
|
+
),
|
|
63
|
+
migrations.AddField(
|
|
64
|
+
model_name='contacttype',
|
|
65
|
+
name='is_active',
|
|
66
|
+
field=models.BooleanField(default=True),
|
|
67
|
+
),
|
|
68
|
+
migrations.AddField(
|
|
69
|
+
model_name='contacttype',
|
|
70
|
+
name='updated_at',
|
|
71
|
+
field=models.DateTimeField(auto_now=True),
|
|
72
|
+
),
|
|
73
|
+
migrations.AddField(
|
|
74
|
+
model_name='entity',
|
|
75
|
+
name='created_at',
|
|
76
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
77
|
+
preserve_default=False,
|
|
78
|
+
),
|
|
79
|
+
migrations.AddField(
|
|
80
|
+
model_name='entity',
|
|
81
|
+
name='is_active',
|
|
82
|
+
field=models.BooleanField(default=True),
|
|
83
|
+
),
|
|
84
|
+
migrations.AddField(
|
|
85
|
+
model_name='entity',
|
|
86
|
+
name='updated_at',
|
|
87
|
+
field=models.DateTimeField(auto_now=True),
|
|
88
|
+
),
|
|
89
|
+
migrations.AddField(
|
|
90
|
+
model_name='message',
|
|
91
|
+
name='is_active',
|
|
92
|
+
field=models.BooleanField(default=True),
|
|
93
|
+
),
|
|
94
|
+
migrations.AddField(
|
|
95
|
+
model_name='message',
|
|
96
|
+
name='updated_at',
|
|
97
|
+
field=models.DateTimeField(auto_now=True),
|
|
98
|
+
),
|
|
99
|
+
migrations.AddField(
|
|
100
|
+
model_name='module',
|
|
101
|
+
name='created_at',
|
|
102
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
103
|
+
preserve_default=False,
|
|
104
|
+
),
|
|
105
|
+
migrations.AddField(
|
|
106
|
+
model_name='module',
|
|
107
|
+
name='updated_at',
|
|
108
|
+
field=models.DateTimeField(auto_now=True),
|
|
109
|
+
),
|
|
110
|
+
migrations.AddField(
|
|
111
|
+
model_name='organization',
|
|
112
|
+
name='created_at',
|
|
113
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
114
|
+
preserve_default=False,
|
|
115
|
+
),
|
|
116
|
+
migrations.AddField(
|
|
117
|
+
model_name='organization',
|
|
118
|
+
name='is_active',
|
|
119
|
+
field=models.BooleanField(default=True),
|
|
120
|
+
),
|
|
121
|
+
migrations.AddField(
|
|
122
|
+
model_name='organization',
|
|
123
|
+
name='updated_at',
|
|
124
|
+
field=models.DateTimeField(auto_now=True),
|
|
125
|
+
),
|
|
126
|
+
migrations.AddField(
|
|
127
|
+
model_name='organizationmodule',
|
|
128
|
+
name='is_active',
|
|
129
|
+
field=models.BooleanField(default=True),
|
|
130
|
+
),
|
|
131
|
+
migrations.AddField(
|
|
132
|
+
model_name='organizationrole',
|
|
133
|
+
name='created_at',
|
|
134
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
135
|
+
preserve_default=False,
|
|
136
|
+
),
|
|
137
|
+
migrations.AddField(
|
|
138
|
+
model_name='organizationrole',
|
|
139
|
+
name='is_active',
|
|
140
|
+
field=models.BooleanField(default=True),
|
|
141
|
+
),
|
|
142
|
+
migrations.AddField(
|
|
143
|
+
model_name='organizationrole',
|
|
144
|
+
name='updated_at',
|
|
145
|
+
field=models.DateTimeField(auto_now=True),
|
|
146
|
+
),
|
|
147
|
+
migrations.AddField(
|
|
148
|
+
model_name='organizationuser',
|
|
149
|
+
name='created_at',
|
|
150
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
151
|
+
preserve_default=False,
|
|
152
|
+
),
|
|
153
|
+
migrations.AddField(
|
|
154
|
+
model_name='organizationuser',
|
|
155
|
+
name='is_active',
|
|
156
|
+
field=models.BooleanField(default=True),
|
|
157
|
+
),
|
|
158
|
+
migrations.AddField(
|
|
159
|
+
model_name='organizationuser',
|
|
160
|
+
name='updated_at',
|
|
161
|
+
field=models.DateTimeField(auto_now=True),
|
|
162
|
+
),
|
|
163
|
+
migrations.AddField(
|
|
164
|
+
model_name='person',
|
|
165
|
+
name='created_at',
|
|
166
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
167
|
+
preserve_default=False,
|
|
168
|
+
),
|
|
169
|
+
migrations.AddField(
|
|
170
|
+
model_name='person',
|
|
171
|
+
name='is_active',
|
|
172
|
+
field=models.BooleanField(default=True),
|
|
173
|
+
),
|
|
174
|
+
migrations.AddField(
|
|
175
|
+
model_name='person',
|
|
176
|
+
name='updated_at',
|
|
177
|
+
field=models.DateTimeField(auto_now=True),
|
|
178
|
+
),
|
|
179
|
+
migrations.AddField(
|
|
180
|
+
model_name='personcontact',
|
|
181
|
+
name='created_at',
|
|
182
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
183
|
+
preserve_default=False,
|
|
184
|
+
),
|
|
185
|
+
migrations.AddField(
|
|
186
|
+
model_name='personcontact',
|
|
187
|
+
name='is_active',
|
|
188
|
+
field=models.BooleanField(default=True),
|
|
189
|
+
),
|
|
190
|
+
migrations.AddField(
|
|
191
|
+
model_name='personcontact',
|
|
192
|
+
name='updated_at',
|
|
193
|
+
field=models.DateTimeField(auto_now=True),
|
|
194
|
+
),
|
|
195
|
+
migrations.AddField(
|
|
196
|
+
model_name='persontag',
|
|
197
|
+
name='created_at',
|
|
198
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
199
|
+
preserve_default=False,
|
|
200
|
+
),
|
|
201
|
+
migrations.AddField(
|
|
202
|
+
model_name='persontag',
|
|
203
|
+
name='is_active',
|
|
204
|
+
field=models.BooleanField(default=True),
|
|
205
|
+
),
|
|
206
|
+
migrations.AddField(
|
|
207
|
+
model_name='persontag',
|
|
208
|
+
name='updated_at',
|
|
209
|
+
field=models.DateTimeField(auto_now=True),
|
|
210
|
+
),
|
|
211
|
+
migrations.AddField(
|
|
212
|
+
model_name='persontagged',
|
|
213
|
+
name='created_at',
|
|
214
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
215
|
+
preserve_default=False,
|
|
216
|
+
),
|
|
217
|
+
migrations.AddField(
|
|
218
|
+
model_name='persontagged',
|
|
219
|
+
name='is_active',
|
|
220
|
+
field=models.BooleanField(default=True),
|
|
221
|
+
),
|
|
222
|
+
migrations.AddField(
|
|
223
|
+
model_name='persontagged',
|
|
224
|
+
name='updated_at',
|
|
225
|
+
field=models.DateTimeField(auto_now=True),
|
|
226
|
+
),
|
|
227
|
+
migrations.AddField(
|
|
228
|
+
model_name='role',
|
|
229
|
+
name='created_at',
|
|
230
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
231
|
+
preserve_default=False,
|
|
232
|
+
),
|
|
233
|
+
migrations.AddField(
|
|
234
|
+
model_name='role',
|
|
235
|
+
name='is_active',
|
|
236
|
+
field=models.BooleanField(default=True),
|
|
237
|
+
),
|
|
238
|
+
migrations.AddField(
|
|
239
|
+
model_name='role',
|
|
240
|
+
name='updated_at',
|
|
241
|
+
field=models.DateTimeField(auto_now=True),
|
|
242
|
+
),
|
|
243
|
+
migrations.AddField(
|
|
244
|
+
model_name='system',
|
|
245
|
+
name='is_active',
|
|
246
|
+
field=models.BooleanField(default=True),
|
|
247
|
+
),
|
|
248
|
+
migrations.AddField(
|
|
249
|
+
model_name='tagcategory',
|
|
250
|
+
name='created_at',
|
|
251
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
252
|
+
preserve_default=False,
|
|
253
|
+
),
|
|
254
|
+
migrations.AddField(
|
|
255
|
+
model_name='tagcategory',
|
|
256
|
+
name='is_active',
|
|
257
|
+
field=models.BooleanField(default=True),
|
|
258
|
+
),
|
|
259
|
+
migrations.AddField(
|
|
260
|
+
model_name='tagcategory',
|
|
261
|
+
name='updated_at',
|
|
262
|
+
field=models.DateTimeField(auto_now=True),
|
|
263
|
+
),
|
|
264
|
+
migrations.AddField(
|
|
265
|
+
model_name='user',
|
|
266
|
+
name='created_at',
|
|
267
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
268
|
+
preserve_default=False,
|
|
269
|
+
),
|
|
270
|
+
migrations.AddField(
|
|
271
|
+
model_name='user',
|
|
272
|
+
name='is_active',
|
|
273
|
+
field=models.BooleanField(default=True),
|
|
274
|
+
),
|
|
275
|
+
migrations.AddField(
|
|
276
|
+
model_name='user',
|
|
277
|
+
name='updated_at',
|
|
278
|
+
field=models.DateTimeField(auto_now=True),
|
|
279
|
+
),
|
|
280
|
+
migrations.AddField(
|
|
281
|
+
model_name='usercompanyaccess',
|
|
282
|
+
name='created_at',
|
|
283
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
284
|
+
preserve_default=False,
|
|
285
|
+
),
|
|
286
|
+
migrations.AddField(
|
|
287
|
+
model_name='usercompanyaccess',
|
|
288
|
+
name='is_active',
|
|
289
|
+
field=models.BooleanField(default=True),
|
|
290
|
+
),
|
|
291
|
+
migrations.AddField(
|
|
292
|
+
model_name='usercompanyaccess',
|
|
293
|
+
name='updated_at',
|
|
294
|
+
field=models.DateTimeField(auto_now=True),
|
|
295
|
+
),
|
|
296
|
+
migrations.AddField(
|
|
297
|
+
model_name='usergroup',
|
|
298
|
+
name='created_at',
|
|
299
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
300
|
+
preserve_default=False,
|
|
301
|
+
),
|
|
302
|
+
migrations.AddField(
|
|
303
|
+
model_name='usergroup',
|
|
304
|
+
name='is_active',
|
|
305
|
+
field=models.BooleanField(default=True),
|
|
306
|
+
),
|
|
307
|
+
migrations.AddField(
|
|
308
|
+
model_name='usergroup',
|
|
309
|
+
name='updated_at',
|
|
310
|
+
field=models.DateTimeField(auto_now=True),
|
|
311
|
+
),
|
|
312
|
+
migrations.AddField(
|
|
313
|
+
model_name='userrole',
|
|
314
|
+
name='created_at',
|
|
315
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
316
|
+
preserve_default=False,
|
|
317
|
+
),
|
|
318
|
+
migrations.AddField(
|
|
319
|
+
model_name='userrole',
|
|
320
|
+
name='is_active',
|
|
321
|
+
field=models.BooleanField(default=True),
|
|
322
|
+
),
|
|
323
|
+
migrations.AddField(
|
|
324
|
+
model_name='userrole',
|
|
325
|
+
name='updated_at',
|
|
326
|
+
field=models.DateTimeField(auto_now=True),
|
|
327
|
+
),
|
|
328
|
+
migrations.AlterField(
|
|
329
|
+
model_name='entityauth',
|
|
330
|
+
name='is_active',
|
|
331
|
+
field=models.BooleanField(default=True),
|
|
332
|
+
),
|
|
333
|
+
migrations.AlterField(
|
|
334
|
+
model_name='system',
|
|
335
|
+
name='created_at',
|
|
336
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
337
|
+
preserve_default=False,
|
|
338
|
+
),
|
|
339
|
+
migrations.AlterField(
|
|
340
|
+
model_name='system',
|
|
341
|
+
name='updated_at',
|
|
342
|
+
field=models.DateTimeField(auto_now=True, default=django.utils.timezone.now),
|
|
343
|
+
preserve_default=False,
|
|
344
|
+
),
|
|
345
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Generated manually on 2026-02-02 for automations schema
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
import django.db.models.deletion
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
('constec_db', '0004_rename_entities_company_cuit_idx_entities_company_e2c50f_idx_and_more'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.CreateModel(
|
|
17
|
+
name='Event',
|
|
18
|
+
fields=[
|
|
19
|
+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
20
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
21
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
22
|
+
('event_type', models.CharField(choices=[('notification', 'Notification'), ('automation', 'Automation')], max_length=50)),
|
|
23
|
+
('title', models.CharField(max_length=255)),
|
|
24
|
+
('description', models.TextField(blank=True)),
|
|
25
|
+
('status', models.CharField(choices=[('active', 'Active'), ('paused', 'Paused'), ('completed', 'Completed'), ('failed', 'Failed'), ('cancelled', 'Cancelled')], default='active', max_length=20)),
|
|
26
|
+
('recurrence_type', models.CharField(choices=[('punctual', 'Punctual'), ('periodic', 'Periodic')], help_text='Tipo de recurrencia: puntual (fechas específicas) o periódico', max_length=20)),
|
|
27
|
+
('recurrence_config', models.JSONField(help_text='Configuración de recurrencia en formato JSON')),
|
|
28
|
+
('config', models.JSONField(default=dict, help_text='Configuración específica según event_type (mensaje, URL, etc.)')),
|
|
29
|
+
('next_execution_at', models.DateTimeField(blank=True, db_index=True, help_text='Próxima fecha/hora de ejecución calculada', null=True)),
|
|
30
|
+
('last_executed_at', models.DateTimeField(blank=True, help_text='Última vez que se ejecutó', null=True)),
|
|
31
|
+
('execution_count', models.IntegerField(default=0, help_text='Cantidad de veces que se ha ejecutado')),
|
|
32
|
+
('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='constec_db.company')),
|
|
33
|
+
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_events', to=settings.AUTH_USER_MODEL)),
|
|
34
|
+
],
|
|
35
|
+
options={
|
|
36
|
+
'db_table': '"automations"."events"',
|
|
37
|
+
'ordering': ['next_execution_at'],
|
|
38
|
+
'indexes': [
|
|
39
|
+
models.Index(fields=['company', 'event_type'], name='automations_company_ebe85a_idx'),
|
|
40
|
+
models.Index(fields=['status', 'next_execution_at'], name='automations_status_a3d45f_idx'),
|
|
41
|
+
models.Index(fields=['recurrence_type'], name='automations_recurre_5d8b2c_idx'),
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
bases=(models.Model,),
|
|
45
|
+
),
|
|
46
|
+
]
|
|
@@ -41,6 +41,9 @@ ErpEntity = Entity
|
|
|
41
41
|
from .flow import FlowTemplate, Flow
|
|
42
42
|
from .session import Session, Message
|
|
43
43
|
|
|
44
|
+
# Automations models (automations schema)
|
|
45
|
+
from .automation import Event
|
|
46
|
+
|
|
44
47
|
|
|
45
48
|
__all__ = [
|
|
46
49
|
# Base
|
|
@@ -89,4 +92,6 @@ __all__ = [
|
|
|
89
92
|
'Flow',
|
|
90
93
|
'Session',
|
|
91
94
|
'Message',
|
|
95
|
+
# Automations (automations schema)
|
|
96
|
+
'Event',
|
|
92
97
|
]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Automation models for event scheduling and task automation."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from django.db import models
|
|
5
|
+
from .base import UUIDModel
|
|
6
|
+
from .company import Company
|
|
7
|
+
from .user import User
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Event(UUIDModel):
|
|
11
|
+
"""
|
|
12
|
+
Evento programado con soporte para múltiples tipos y recurrencia flexible.
|
|
13
|
+
|
|
14
|
+
Tipos soportados:
|
|
15
|
+
- notification: Notificaciones programadas
|
|
16
|
+
- automation: Automatizaciones programadas (acciones HTTP, workflows, etc.)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
EVENT_TYPE_CHOICES = [
|
|
20
|
+
('notification', 'Notification'),
|
|
21
|
+
('automation', 'Automation'),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
STATUS_CHOICES = [
|
|
25
|
+
('active', 'Active'), # Activo y programado
|
|
26
|
+
('paused', 'Paused'), # Pausado temporalmente
|
|
27
|
+
('completed', 'Completed'), # Completado (para puntuales)
|
|
28
|
+
('failed', 'Failed'), # Falló la última ejecución
|
|
29
|
+
('cancelled', 'Cancelled'), # Cancelado permanentemente
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
RECURRENCE_TYPE_CHOICES = [
|
|
33
|
+
('punctual', 'Punctual'), # Una o más veces en fechas específicas
|
|
34
|
+
('periodic', 'Periodic'), # Recurrente
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
# FKs
|
|
38
|
+
company = models.ForeignKey(Company, on_delete=models.CASCADE, db_index=True)
|
|
39
|
+
|
|
40
|
+
# Tipo de evento
|
|
41
|
+
event_type = models.CharField(max_length=50, choices=EVENT_TYPE_CHOICES)
|
|
42
|
+
|
|
43
|
+
# Info básica
|
|
44
|
+
title = models.CharField(max_length=255)
|
|
45
|
+
description = models.TextField(blank=True)
|
|
46
|
+
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
|
|
47
|
+
|
|
48
|
+
# Recurrencia
|
|
49
|
+
recurrence_type = models.CharField(
|
|
50
|
+
max_length=20,
|
|
51
|
+
choices=RECURRENCE_TYPE_CHOICES,
|
|
52
|
+
help_text="Tipo de recurrencia: puntual (fechas específicas) o periódico"
|
|
53
|
+
)
|
|
54
|
+
recurrence_config = models.JSONField(
|
|
55
|
+
help_text="Configuración de recurrencia en formato JSON"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Configuración específica del tipo de evento
|
|
59
|
+
config = models.JSONField(
|
|
60
|
+
default=dict,
|
|
61
|
+
help_text="Configuración específica según event_type (mensaje, URL, etc.)"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Control de ejecución
|
|
65
|
+
next_execution_at = models.DateTimeField(
|
|
66
|
+
null=True,
|
|
67
|
+
blank=True,
|
|
68
|
+
db_index=True,
|
|
69
|
+
help_text="Próxima fecha/hora de ejecución calculada"
|
|
70
|
+
)
|
|
71
|
+
last_executed_at = models.DateTimeField(
|
|
72
|
+
null=True,
|
|
73
|
+
blank=True,
|
|
74
|
+
help_text="Última vez que se ejecutó"
|
|
75
|
+
)
|
|
76
|
+
execution_count = models.IntegerField(
|
|
77
|
+
default=0,
|
|
78
|
+
help_text="Cantidad de veces que se ha ejecutado"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Auditoría
|
|
82
|
+
created_by = models.ForeignKey(
|
|
83
|
+
User,
|
|
84
|
+
on_delete=models.CASCADE,
|
|
85
|
+
related_name='created_events'
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
class Meta:
|
|
89
|
+
db_table = '"automations"."events"'
|
|
90
|
+
app_label = 'constec_db'
|
|
91
|
+
indexes = [
|
|
92
|
+
models.Index(fields=['company', 'event_type']),
|
|
93
|
+
models.Index(fields=['status', 'next_execution_at']),
|
|
94
|
+
models.Index(fields=['recurrence_type']),
|
|
95
|
+
]
|
|
96
|
+
ordering = ['next_execution_at']
|
|
97
|
+
|
|
98
|
+
def __str__(self):
|
|
99
|
+
return f"{self.event_type}: {self.title}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from django.db import models
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class UUIDModel(models.Model):
|
|
6
|
+
"""Base model with UUID primary key and common audit fields.
|
|
7
|
+
|
|
8
|
+
All Constec models inherit from this to ensure consistent
|
|
9
|
+
UUID-based primary keys and audit fields across the platform.
|
|
10
|
+
|
|
11
|
+
Fields provided:
|
|
12
|
+
- id: UUID primary key
|
|
13
|
+
- is_active: soft delete flag
|
|
14
|
+
- created_at: auto-set on creation
|
|
15
|
+
- updated_at: auto-set on every save
|
|
16
|
+
"""
|
|
17
|
+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
18
|
+
is_active = models.BooleanField(default=True)
|
|
19
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
20
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
21
|
+
|
|
22
|
+
class Meta:
|
|
23
|
+
abstract = True
|
|
@@ -12,12 +12,10 @@ class System(UUIDModel):
|
|
|
12
12
|
description = models.TextField(blank=True, null=True)
|
|
13
13
|
api_endpoint = models.URLField(max_length=200, blank=True)
|
|
14
14
|
metadata = models.JSONField(default=dict, blank=True)
|
|
15
|
-
created_at = models.DateTimeField(auto_now_add=True, null=True)
|
|
16
|
-
updated_at = models.DateTimeField(auto_now=True, null=True)
|
|
17
15
|
|
|
18
16
|
class Meta:
|
|
19
17
|
app_label = 'constec_db'
|
|
20
|
-
db_table = '
|
|
18
|
+
db_table = 'erp"."systems'
|
|
21
19
|
|
|
22
20
|
def __str__(self):
|
|
23
21
|
return f"{self.name}"
|
|
@@ -44,14 +42,11 @@ class CompanySystem(UUIDModel):
|
|
|
44
42
|
default=False,
|
|
45
43
|
help_text="Whether this is the primary ERP system for the company"
|
|
46
44
|
)
|
|
47
|
-
is_active = models.BooleanField(default=True)
|
|
48
45
|
metadata = models.JSONField(default=dict, blank=True)
|
|
49
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
50
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
51
46
|
|
|
52
47
|
class Meta:
|
|
53
48
|
app_label = 'constec_db'
|
|
54
|
-
db_table = '
|
|
49
|
+
db_table = 'erp"."company_systems'
|
|
55
50
|
unique_together = [['company', 'system']]
|
|
56
51
|
indexes = [
|
|
57
52
|
models.Index(fields=['company', 'is_primary']),
|
|
@@ -95,14 +90,11 @@ class Connection(UUIDModel):
|
|
|
95
90
|
database = models.CharField(max_length=100)
|
|
96
91
|
username = models.CharField(max_length=100)
|
|
97
92
|
encrypted_password = models.TextField()
|
|
98
|
-
is_active = models.BooleanField(default=True)
|
|
99
93
|
last_tested_at = models.DateTimeField(null=True, blank=True)
|
|
100
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
101
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
102
94
|
|
|
103
95
|
class Meta:
|
|
104
96
|
app_label = 'constec_db'
|
|
105
|
-
db_table = '
|
|
97
|
+
db_table = 'erp"."connections'
|
|
106
98
|
unique_together = [['system', 'slug']]
|
|
107
99
|
|
|
108
100
|
def __str__(self):
|
|
@@ -18,7 +18,7 @@ class Role(UUIDModel):
|
|
|
18
18
|
|
|
19
19
|
class Meta:
|
|
20
20
|
app_label = 'constec_db'
|
|
21
|
-
db_table = '
|
|
21
|
+
db_table = 'erp"."roles'
|
|
22
22
|
unique_together = [['system', 'name']]
|
|
23
23
|
|
|
24
24
|
def __str__(self):
|
|
@@ -69,7 +69,7 @@ class Entity(UUIDModel):
|
|
|
69
69
|
|
|
70
70
|
class Meta:
|
|
71
71
|
app_label = 'constec_db'
|
|
72
|
-
db_table = '
|
|
72
|
+
db_table = 'erp"."entities'
|
|
73
73
|
verbose_name_plural = 'Entities'
|
|
74
74
|
unique_together = [['company', 'role', 'external_id']]
|
|
75
75
|
indexes = [
|
|
@@ -105,12 +105,6 @@ class EntityAuth(UUIDModel):
|
|
|
105
105
|
max_length=255,
|
|
106
106
|
help_text="Bcrypt hashed password"
|
|
107
107
|
)
|
|
108
|
-
is_active = models.BooleanField(
|
|
109
|
-
default=True,
|
|
110
|
-
help_text="Whether this account can authenticate"
|
|
111
|
-
)
|
|
112
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
113
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
114
108
|
last_login = models.DateTimeField(
|
|
115
109
|
null=True,
|
|
116
110
|
blank=True,
|
|
@@ -119,7 +113,7 @@ class EntityAuth(UUIDModel):
|
|
|
119
113
|
|
|
120
114
|
class Meta:
|
|
121
115
|
app_label = 'constec_db'
|
|
122
|
-
db_table = '
|
|
116
|
+
db_table = 'erp"."entity_auth'
|
|
123
117
|
verbose_name = "Entity Authentication"
|
|
124
118
|
verbose_name_plural = "Entity Authentications"
|
|
125
119
|
|
|
@@ -46,7 +46,6 @@ class FlowTemplate(UUIDModel):
|
|
|
46
46
|
default=False,
|
|
47
47
|
help_text="If true, all organizations can use this template"
|
|
48
48
|
)
|
|
49
|
-
is_active = models.BooleanField(default=True)
|
|
50
49
|
|
|
51
50
|
version = models.CharField(max_length=20, default="1.0.0")
|
|
52
51
|
created_by = models.ForeignKey(
|
|
@@ -55,8 +54,6 @@ class FlowTemplate(UUIDModel):
|
|
|
55
54
|
null=True,
|
|
56
55
|
related_name="created_templates"
|
|
57
56
|
)
|
|
58
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
59
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
60
57
|
|
|
61
58
|
class Meta:
|
|
62
59
|
app_label = 'constec_db'
|
|
@@ -108,15 +105,11 @@ class Flow(UUIDModel):
|
|
|
108
105
|
help_text="Configuration that merges with template.default_config"
|
|
109
106
|
)
|
|
110
107
|
|
|
111
|
-
is_active = models.BooleanField(default=True)
|
|
112
108
|
is_default = models.BooleanField(
|
|
113
109
|
default=False,
|
|
114
110
|
help_text="Whether this is the default flow for the company"
|
|
115
111
|
)
|
|
116
112
|
|
|
117
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
118
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
119
|
-
|
|
120
113
|
class Meta:
|
|
121
114
|
app_label = 'constec_db'
|
|
122
115
|
db_table = 'constancia"."flows'
|
|
@@ -10,7 +10,6 @@ class Module(UUIDModel):
|
|
|
10
10
|
slug = models.SlugField(max_length=100, null=True)
|
|
11
11
|
description = models.TextField(blank=True, null=True)
|
|
12
12
|
version = models.CharField(max_length=20)
|
|
13
|
-
is_active = models.BooleanField(default=True)
|
|
14
13
|
|
|
15
14
|
class Meta:
|
|
16
15
|
app_label = 'constec_db'
|
|
@@ -36,10 +36,7 @@ class Session(UUIDModel):
|
|
|
36
36
|
help_text="Session context (connection, role, etc.)"
|
|
37
37
|
)
|
|
38
38
|
|
|
39
|
-
is_active = models.BooleanField(default=True)
|
|
40
39
|
ended_at = models.DateTimeField(null=True, blank=True)
|
|
41
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
42
|
-
updated_at = models.DateTimeField(auto_now=True)
|
|
43
40
|
|
|
44
41
|
class Meta:
|
|
45
42
|
app_label = 'constec_db'
|
|
@@ -79,8 +76,6 @@ class Message(UUIDModel):
|
|
|
79
76
|
help_text="Additional message data: tool calls, errors, context, etc."
|
|
80
77
|
)
|
|
81
78
|
|
|
82
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
83
|
-
|
|
84
79
|
class Meta:
|
|
85
80
|
app_label = 'constec_db'
|
|
86
81
|
db_table = 'constancia"."messages'
|
|
@@ -12,8 +12,11 @@ constec/db/apps.py
|
|
|
12
12
|
constec/db/migrations/0001_initial.py
|
|
13
13
|
constec/db/migrations/0002_module_level.py
|
|
14
14
|
constec/db/migrations/0003_remove_module_level.py
|
|
15
|
+
constec/db/migrations/0004_rename_entities_company_cuit_idx_entities_company_e2c50f_idx_and_more.py
|
|
16
|
+
constec/db/migrations/0005_event.py
|
|
15
17
|
constec/db/migrations/__init__.py
|
|
16
18
|
constec/db/models/__init__.py
|
|
19
|
+
constec/db/models/automation.py
|
|
17
20
|
constec/db/models/base.py
|
|
18
21
|
constec/db/models/company.py
|
|
19
22
|
constec/db/models/contact.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "constec"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.1"
|
|
8
8
|
description = "Base library for the Constec ecosystem - shared utilities, models, and namespace foundation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
from django.db import models
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class UUIDModel(models.Model):
|
|
6
|
-
"""Base model with UUID as primary key.
|
|
7
|
-
|
|
8
|
-
All Constec models inherit from this to ensure consistent
|
|
9
|
-
UUID-based primary keys across the platform.
|
|
10
|
-
"""
|
|
11
|
-
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
12
|
-
|
|
13
|
-
class Meta:
|
|
14
|
-
abstract = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|