feature/T2026-05-016-y-T2026-05-031 #28

Merged
jcedilloAS merged 4 commits from feature/T2026-05-016-y-T2026-05-031 into main 2026-05-18 18:05:27 +00:00
6 changed files with 35 additions and 11 deletions
Showing only changes of commit 63f051c566 - Show all commits

View File

@@ -13,7 +13,7 @@ class CustomUserCreationForm(UserCreationForm):
class CustomUserChangeForm(UserChangeForm): class CustomUserChangeForm(UserChangeForm):
class Meta: class Meta:
model = CustomUser model = CustomUser
fields = ('username', 'email', 'first_name', 'last_name', 'organizacion', 'profile_picture') fields = ('username', 'email', 'first_name', 'last_name', 'organizacion', 'profile_picture', 'is_importador', 'rfc')
class CustomUserAdmin(UserAdmin): class CustomUserAdmin(UserAdmin):
@@ -25,6 +25,7 @@ class CustomUserAdmin(UserAdmin):
list_filter = ('is_staff', 'is_active', 'organizacion') list_filter = ('is_staff', 'is_active', 'organizacion')
search_fields = ('username', 'email', 'first_name', 'last_name') search_fields = ('username', 'email', 'first_name', 'last_name')
ordering = ('username',) ordering = ('username',)
filter_horizontal = ('rfc', 'groups', 'user_permissions')
# Fieldsets para editar un usuario # Fieldsets para editar un usuario
fieldsets = ( fieldsets = (

View File

@@ -12,7 +12,7 @@ class CustomUser(AbstractUser):
profile_picture = models.ImageField(upload_to='profile_pictures/', null=True, blank=True) profile_picture = models.ImageField(upload_to='profile_pictures/', null=True, blank=True)
is_importador = models.BooleanField(default=False, help_text="Indicates if the user is an importer") is_importador = models.BooleanField(default=False, help_text="Indicates if the user is an importer")
rfc = models.ForeignKey('customs.Importador', on_delete=models.SET_NULL, null=True, blank=True, related_name='users', help_text="RFC associated with the user if they are an importer") rfc = models.ManyToManyField('customs.Importador', blank=True, related_name='users', help_text="RFCs de importadores asociados al usuario")
def __str__(self): def __str__(self):
return self.username return self.username

View File

@@ -2,6 +2,7 @@
from rest_framework import serializers from rest_framework import serializers
from .models import CustomUser from .models import CustomUser
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from api.customs.models import Importador
class CustomUserSerializer(serializers.ModelSerializer): class CustomUserSerializer(serializers.ModelSerializer):
""" """
@@ -10,8 +11,12 @@ class CustomUserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True) password = serializers.CharField(write_only=True)
groups = serializers.PrimaryKeyRelatedField(queryset=Group.objects.all(), many=True, required=False) groups = serializers.PrimaryKeyRelatedField(queryset=Group.objects.all(), many=True, required=False)
rfc = serializers.CharField(max_length=20, required=False, allow_blank=True) rfc = serializers.PrimaryKeyRelatedField(
queryset=Importador.objects.all(),
many=True,
required=False,
pk_field=serializers.CharField(),
)
class Meta: class Meta:
model = CustomUser model = CustomUser
@@ -20,10 +25,28 @@ class CustomUserSerializer(serializers.ModelSerializer):
def create(self, validated_data): def create(self, validated_data):
groups = validated_data.pop('groups', []) groups = validated_data.pop('groups', [])
rfcs = validated_data.pop('rfc', [])
password = validated_data.pop('password') password = validated_data.pop('password')
user = CustomUser(**validated_data) user = CustomUser(**validated_data)
user.set_password(password) user.set_password(password)
user.save() user.save()
if groups: if groups:
user.groups.set(groups) user.groups.set(groups)
if rfcs:
user.rfc.set(rfcs)
return user return user
def update(self, instance, validated_data):
groups = validated_data.pop('groups', None)
rfcs = validated_data.pop('rfc', None)
password = validated_data.pop('password', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
if password:
instance.set_password(password)
instance.save()
if groups is not None:
instance.groups.set(groups)
if rfcs is not None:
instance.rfc.set(rfcs)
return instance

View File

@@ -19,7 +19,7 @@ def trigger_notificacion(sender, instance, created, **kwargs):
for usuario in usuarios_org: for usuario in usuarios_org:
# Notificar solo a importadores cuyo RFC coincide # Notificar solo a importadores cuyo RFC coincide
if (usuario.is_importador or usuario.groups.filter(name='Importador').exists()): if (usuario.is_importador or usuario.groups.filter(name='Importador').exists()):
if usuario.rfc == instance.pedimento.contribuyente: if instance.pedimento.contribuyente in usuario.rfc.all():
Notificacion.objects.create( Notificacion.objects.create(
tipo=tipo_info, tipo=tipo_info,
dirigido=usuario, dirigido=usuario,

View File

@@ -84,7 +84,7 @@ class VucemView(viewsets.ModelViewSet):
elif not hasattr(self.request.user, 'organizacion') or not self.request.user.organizacion: elif not hasattr(self.request.user, 'organizacion') or not self.request.user.organizacion:
return queryset.none() return queryset.none()
elif self.request.user.groups.filter(name='Importador').exists(): elif self.request.user.groups.filter(name='Importador').exists():
queryset = queryset.filter(organizacion=self.request.user.organizacion, usuario=self.request.user.rfc) queryset = queryset.filter(organizacion=self.request.user.organizacion, usuario__in=self.request.user.rfc.all())
else: else:
queryset = queryset.filter(organizacion=self.request.user.organizacion) queryset = queryset.filter(organizacion=self.request.user.organizacion)

View File

@@ -63,7 +63,7 @@ class OrganizacionFiltradaMixin:
# if hasattr(model, self.campo_contribuyente): # if hasattr(model, self.campo_contribuyente):
if self.request.user.is_authenticated and 'Importador' in grupos: if self.request.user.is_authenticated and 'Importador' in grupos:
filtros_base[f"{self.campo_contribuyente}__rfc"] = self.request.user.rfc.rfc filtros_base[f"{self.campo_contribuyente}__in"] = self.request.user.rfc.all()
return model.objects.filter(**filtros_base) return model.objects.filter(**filtros_base)
# Si no entra en los roles válidos # Si no entra en los roles válidos
@@ -98,7 +98,7 @@ class DocumentosFiltradosMixin:
if hasattr(model, self.campo_contribuyente): if hasattr(model, self.campo_contribuyente):
if self.request.user.is_authenticated and 'Importador' in grupos and getattr(self.request.user, 'is_importador', False): if self.request.user.is_authenticated and 'Importador' in grupos and getattr(self.request.user, 'is_importador', False):
filtros_base[f"{self.campo_contribuyente}__contribuyente"] = self.request.user.rfc filtros_base[f"{self.campo_contribuyente}__contribuyente__in"] = self.request.user.rfc.all()
return model.objects.filter(**filtros_base) return model.objects.filter(**filtros_base)
# Si no entra en los roles válidos # Si no entra en los roles válidos
@@ -134,7 +134,7 @@ class ProcesosPorOrganizacionMixin:
if hasattr(model, self.campo_pedimento): if hasattr(model, self.campo_pedimento):
if self.request.user.is_authenticated and 'Importador' in grupos and getattr(self.request.user, 'is_importador', False): if self.request.user.is_authenticated and 'Importador' in grupos and getattr(self.request.user, 'is_importador', False):
filtros_base[f"{self.campo_pedimento}__contribuyente"] = self.request.user.rfc filtros_base[f"{self.campo_pedimento}__contribuyente__in"] = self.request.user.rfc.all()
return model.objects.filter(**filtros_base) return model.objects.filter(**filtros_base)
# Si no entra en los roles válidos # Si no entra en los roles válidos