feat(logs): add workspace activity log api

This commit is contained in:
2026-04-28 16:42:37 +03:30
parent c8a118788b
commit 71924ce6fb
32 changed files with 1118 additions and 122 deletions

View File

@@ -1,47 +1,47 @@
# Generated by Django 5.2.12 on 2026-04-26 19:23
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('workspaces', '0005_remove_priceunit_priceunit_id_idx_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ReportExportJob',
fields=[
('id', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
('is_deleted', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=False)),
('export_type', models.CharField(choices=[('excel', 'Excel'), ('pdf', 'PDF')], max_length=16)),
('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('completed', 'Completed'), ('failed', 'Failed'), ('expired', 'Expired')], default='pending', max_length=16)),
('filters', models.JSONField(default=dict)),
('file', models.FileField(blank=True, null=True, upload_to='reports/exports/')),
('file_name', models.CharField(blank=True, max_length=255)),
('error_message', models.TextField(blank=True)),
('expires_at', models.DateTimeField(blank=True, null=True)),
('completed_at', models.DateTimeField(blank=True, null=True)),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(app_label)s_%(class)s_set', to=settings.AUTH_USER_MODEL)),
('requesting_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='report_export_jobs', to=settings.AUTH_USER_MODEL)),
('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(app_label)s_%(class)s_set', to=settings.AUTH_USER_MODEL)),
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='report_export_jobs', to='workspaces.workspace')),
],
options={
'db_table': 'report_export_job',
'ordering': ('-created_at',),
'indexes': [models.Index(fields=['requesting_user'], name='report_export_user_idx'), models.Index(fields=['workspace'], name='report_export_workspace_idx'), models.Index(fields=['status'], name='report_export_status_idx'), models.Index(fields=['expires_at'], name='report_export_expires_idx')],
},
),
]
# Generated by Django 5.2.12 on 2026-04-26 19:23
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('workspaces', '0005_remove_priceunit_priceunit_id_idx_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ReportExportJob',
fields=[
('id', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
('is_deleted', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=False)),
('export_type', models.CharField(choices=[('excel', 'Excel'), ('pdf', 'PDF')], max_length=16)),
('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('completed', 'Completed'), ('failed', 'Failed'), ('expired', 'Expired')], default='pending', max_length=16)),
('filters', models.JSONField(default=dict)),
('file', models.FileField(blank=True, null=True, upload_to='reports/exports/')),
('file_name', models.CharField(blank=True, max_length=255)),
('error_message', models.TextField(blank=True)),
('expires_at', models.DateTimeField(blank=True, null=True)),
('completed_at', models.DateTimeField(blank=True, null=True)),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(app_label)s_%(class)s_set', to=settings.AUTH_USER_MODEL)),
('requesting_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='report_export_jobs', to=settings.AUTH_USER_MODEL)),
('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(app_label)s_%(class)s_set', to=settings.AUTH_USER_MODEL)),
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='report_export_jobs', to='workspaces.workspace')),
],
options={
'db_table': 'report_export_job',
'ordering': ('-created_at',),
'indexes': [models.Index(fields=['requesting_user'], name='report_export_user_idx'), models.Index(fields=['workspace'], name='report_export_workspace_idx'), models.Index(fields=['status'], name='report_export_status_idx'), models.Index(fields=['expires_at'], name='report_export_expires_idx')],
},
),
]

View File

@@ -2,6 +2,8 @@ from django.conf import settings
from django.db import models
from django.utils import timezone
from apps.logs.services import build_workspace_log_metadata
from apps.logs.services.constants import SECTION_REPORT_EXPORTS
from core.models.base import BaseModel
@@ -81,3 +83,14 @@ class ReportExportJob(BaseModel):
self.status = self.Status.EXPIRED
self.save(update_fields=["status", "updated_at"])
def get_additional_data(self):
return build_workspace_log_metadata(
section=SECTION_REPORT_EXPORTS,
workspace_id=self.workspace_id,
target_id=self.id,
target_label=f"{self.export_type.upper()} export",
extra={
"requesting_user_id": str(self.requesting_user_id),
"status": self.status,
},
)