Enzo Yair

crear dos endpoints para comprobantepago

1 from django.contrib import admin 1 from django.contrib import admin
  2 +from django.core.exceptions import ValidationError
  3 +from django.utils import timezone
2 4
3 from .models import Edicto, Precio 5 from .models import Edicto, Precio
4 6
5 # Register your models here. 7 # Register your models here.
6 8
7 -admin.site.register(Precio) 9 +
  10 +class PrecioAdmin(admin.ModelAdmin):
  11 + def save_model(self, request, obj, form, change):
  12 + precios_activos = Precio.objects.filter(vigencia_hasta__gte=timezone.now().date())
  13 + if not change:
  14 + today = timezone.now().date()
  15 + if obj.vigencia_desde <= today:
  16 + if not precios_activos.exists():
  17 + obj.save()
  18 + else:
  19 + raise ValidationError("Ya existe un precio activo.")
  20 + else:
  21 + raise ValidationError("La fecha de inicio no es válida.")
  22 + else:
  23 + obj.save()
  24 +
  25 +
  26 +admin.site.register(Precio, PrecioAdmin)
8 27
9 28
10 admin.site.register(Edicto) 29 admin.site.register(Edicto)
@@ -5,11 +5,12 @@ from rest_framework.permissions import IsAuthenticated @@ -5,11 +5,12 @@ from rest_framework.permissions import IsAuthenticated
5 from rest_framework.decorators import action 5 from rest_framework.decorators import action
6 from datetime import datetime 6 from datetime import datetime
7 7
8 -from .models import Edicto, Precio  
9 -from .serializer import EdictoSerializer, PrecioSerializer 8 +from .models import Edicto, Precio, ComprobantePago
  9 +from .serializer import EdictoSerializer, PrecioSerializer, PagoSerializer, ComprobanteSerializer
10 from .filters import EdictoFilter, PrecioFilter 10 from .filters import EdictoFilter, PrecioFilter
11 from .permissions import IsAdminOrAuthorized 11 from .permissions import IsAdminOrAuthorized
12 from .utils import contador 12 from .utils import contador
  13 +from .precio import calculadora
13 14
14 15
15 class EdictoViewSet(mixins.CreateModelMixin, 16 class EdictoViewSet(mixins.CreateModelMixin,
@@ -54,3 +55,42 @@ class PrecioViewSet(viewsets.ReadOnlyModelViewSet): @@ -54,3 +55,42 @@ class PrecioViewSet(viewsets.ReadOnlyModelViewSet):
54 ordering_fields = ('usuario', ) 55 ordering_fields = ('usuario', )
55 ordering = 'usuario' 56 ordering = 'usuario'
56 queryset = Precio.objects.all() 57 queryset = Precio.objects.all()
  58 +
  59 +
  60 +class PagoViewSets(mixins.CreateModelMixin,
  61 + mixins.RetrieveModelMixin,
  62 + mixins.UpdateModelMixin,
  63 + mixins.DestroyModelMixin,
  64 + mixins.ListModelMixin,
  65 + viewsets.GenericViewSet):
  66 + serializer_class = PagoSerializer
  67 + permission_classes = [IsAuthenticated, IsAdminOrAuthorized]
  68 + queryset = ComprobantePago.objects.all()
  69 +
  70 + def perform_create(self, serializer):
  71 + try:
  72 + edicto = Edicto.objects.get(estado='aprobado')
  73 + precio_admi = Precio.objects.latest('id')
  74 + precio = Precio.objects.get(id=precio_admi.id)
  75 + monto = calculadora(edicto, precio)
  76 + usuario_actual = self.request.user
  77 + if edicto.usuario != usuario_actual:
  78 + raise UsuarioNoAutorizado
  79 + serializer.validated_data['monto'] = monto
  80 + serializer.validated_data['edicto'] = edicto
  81 + serializer.save()
  82 + except Edicto.DoesNotExist:
  83 + raise EdictoNoEncontrado
  84 + except Precio.DoesNotExist:
  85 + raise PrecioNoEncontrado
  86 +
  87 +
  88 +class ComprobanteViewSets(mixins.CreateModelMixin,
  89 + mixins.RetrieveModelMixin,
  90 + mixins.UpdateModelMixin,
  91 + mixins.DestroyModelMixin,
  92 + mixins.ListModelMixin,
  93 + viewsets.GenericViewSet):
  94 + serializer_class = ComprobanteSerializer
  95 + queryset = ComprobantePago.objects.all()
  96 + permission_classes = [IsAuthenticated, ]
@@ -20,12 +20,8 @@ class PrecioFilter(filters.FilterSet): @@ -20,12 +20,8 @@ class PrecioFilter(filters.FilterSet):
20 model = Precio 20 model = Precio
21 fields = { 21 fields = {
22 'usuario': ['exact'], 22 'usuario': ['exact'],
23 - 'precio': ['exact'], 23 + 'precio_palabra': ['exact'],
24 'vigencia_desde': ['exact'], 24 'vigencia_desde': ['exact'],
25 'vigencia_hasta': ['exact'], 25 'vigencia_hasta': ['exact'],
26 'moneda': ['exact'], 26 'moneda': ['exact'],
27 } 27 }
28 -  
29 -  
30 -  
31 -  
  1 +# Generated by Django 4.1.9 on 2023-09-06 14:56
  2 +
  3 +from django.db import migrations, models
  4 +import django.db.models.deletion
  5 +
  6 +
  7 +class Migration(migrations.Migration):
  8 +
  9 + dependencies = [
  10 + ('edicto', '0010_alter_edicto_fecha_creacion'),
  11 + ]
  12 +
  13 + operations = [
  14 + migrations.AlterField(
  15 + model_name='comprobantepago',
  16 + name='edicto',
  17 + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='edicto.edicto'),
  18 + ),
  19 + ]
  1 +# Generated by Django 4.1.9 on 2023-09-06 15:01
  2 +
  3 +from django.db import migrations
  4 +
  5 +
  6 +class Migration(migrations.Migration):
  7 +
  8 + dependencies = [
  9 + ('edicto', '0011_alter_comprobantepago_edicto'),
  10 + ]
  11 +
  12 + operations = [
  13 + migrations.RenameField(
  14 + model_name='precio',
  15 + old_name='precio',
  16 + new_name='precio_palabra',
  17 + ),
  18 + ]
  1 +# Generated by Django 4.1.9 on 2023-09-08 10:13
  2 +
  3 +from django.db import migrations, models
  4 +
  5 +
  6 +class Migration(migrations.Migration):
  7 +
  8 + dependencies = [
  9 + ('edicto', '0012_rename_precio_precio_precio_palabra'),
  10 + ]
  11 +
  12 + operations = [
  13 + migrations.AddField(
  14 + model_name='comprobantepago',
  15 + name='archivo',
  16 + field=models.FileField(null=True, upload_to=''),
  17 + ),
  18 + migrations.AlterField(
  19 + model_name='edicto',
  20 + name='estado',
  21 + field=models.CharField(choices=[('iniciado', 'iniciado'), ('pendiente_de_pago', 'pendiente_de_pago'), ('publicado', 'publicado'), ('aprobado', 'aprobado'), ('rechazado', 'rechazado')], default='iniciado', max_length=150),
  22 + ),
  23 + ]
  1 +# Generated by Django 4.1.9 on 2023-09-08 10:15
  2 +
  3 +from django.db import migrations, models
  4 +
  5 +
  6 +class Migration(migrations.Migration):
  7 +
  8 + dependencies = [
  9 + ('edicto', '0013_comprobantepago_archivo_alter_edicto_estado'),
  10 + ]
  11 +
  12 + operations = [
  13 + migrations.AlterField(
  14 + model_name='comprobantepago',
  15 + name='fecha_pago',
  16 + field=models.DateField(null=True),
  17 + ),
  18 + ]
@@ -8,7 +8,7 @@ from usuario.models import Usuario @@ -8,7 +8,7 @@ from usuario.models import Usuario
8 8
9 9
10 class Precio (models.Model): 10 class Precio (models.Model):
11 - precio = models.FloatField(max_length=50, blank=False, null=False) 11 + precio_palabra = models.FloatField(max_length=50, blank=False, null=False)
12 vigencia_desde = models.DateField() 12 vigencia_desde = models.DateField()
13 vigencia_hasta = models.DateField() 13 vigencia_hasta = models.DateField()
14 usuario = models.ForeignKey(Usuario, on_delete=models.CASCADE) 14 usuario = models.ForeignKey(Usuario, on_delete=models.CASCADE)
@@ -29,7 +29,7 @@ class Edicto(models.Model): @@ -29,7 +29,7 @@ class Edicto(models.Model):
29 archivo = models.FileField(upload_to="uploads/%Y/%m/%d/", null=False, blank=False) 29 archivo = models.FileField(upload_to="uploads/%Y/%m/%d/", null=False, blank=False)
30 dias_publicar = models.PositiveIntegerField(blank=False, null=False) 30 dias_publicar = models.PositiveIntegerField(blank=False, null=False)
31 cantidad_sellos = models.PositiveIntegerField(blank=False, null=False) 31 cantidad_sellos = models.PositiveIntegerField(blank=False, null=False)
32 - estado = models.CharField(max_length=150, choices=STATUS_CHOICE, default='inciado') 32 + estado = models.CharField(max_length=150, choices=STATUS_CHOICE, default='iniciado')
33 cantidad_palabras = models.IntegerField(blank=False, null=False) 33 cantidad_palabras = models.IntegerField(blank=False, null=False)
34 cantidad_copias = models.PositiveIntegerField(blank=False, null=False) 34 cantidad_copias = models.PositiveIntegerField(blank=False, null=False)
35 fecha_publicacion = models.DateField(blank=True, null=True) 35 fecha_publicacion = models.DateField(blank=True, null=True)
@@ -42,18 +42,19 @@ class Edicto(models.Model): @@ -42,18 +42,19 @@ class Edicto(models.Model):
42 verbose_name_plural = 'Edictos' 42 verbose_name_plural = 'Edictos'
43 43
44 def __str__(self): 44 def __str__(self):
45 - return self.cuerpo_edicto 45 + return f"{self.cuerpo_edicto} Edicto"
46 46
47 47
48 class ComprobantePago(models.Model): 48 class ComprobantePago(models.Model):
49 monto = models.FloatField(blank=False, null=False) 49 monto = models.FloatField(blank=False, null=False)
50 numero_comprobante = models.CharField(max_length=300, blank=False, null=True) 50 numero_comprobante = models.CharField(max_length=300, blank=False, null=True)
51 - fecha_pago = models.DateTimeField(blank=False, null=True)  
52 - edicto = models.ForeignKey(Edicto, on_delete=models.CASCADE) 51 + fecha_pago = models.DateField(blank=False, null=True)
  52 + edicto = models.OneToOneField(Edicto, on_delete=models.CASCADE)
  53 + archivo = models.FileField(blank=False, null=True)
53 54
54 class Meta: 55 class Meta:
55 verbose_name = 'ComprobantePago' 56 verbose_name = 'ComprobantePago'
56 verbose_name_plural = 'ComprobantesPagos' 57 verbose_name_plural = 'ComprobantesPagos'
57 58
58 def __str__(self): 59 def __str__(self):
59 - return self.numero_comprobante 60 + return f"{self.numero_comprobante} comprobante pago de {self.edicto.cuerpo_edicto}"
  1 +from django.db import transaction
1 from django.utils import timezone 2 from django.utils import timezone
2 -from .models import Edicto, ComprobantePago, Precio  
3 -  
4 -  
5 -def contador(edicto_id, precio_id):  
6 - edicto = Edicto.objects.select_related('usuario').get(id=edicto_id)  
7 - organismo = edicto.usuario.organismo.es_publico  
8 -  
9 - sellos = edicto.cantidad_sellos  
10 - palabras = edicto.cantidad_palabras  
11 - copias = edicto.cantidad_copias  
12 - publicar = edicto.dias_publicar  
13 -  
14 - precio_valores = Precio.objects.values('precio',  
15 - 'precio_ejemplar',  
16 - 'vigencia_desde',  
17 - 'vigencia_hasta',).get(id=precio_id)  
18 -  
19 - precio = precio_valores['precio']  
20 - precio_ejemplar = precio_valores['precio_ejemplar']  
21 - vigencia_desde = precio_valores['vigencia_desde']  
22 - vigencia_hasta = precio_valores['vigencia_hasta']  
23 -  
24 - current_datetime = timezone.now()  
25 -  
26 - if not (vigencia_desde <= current_datetime <= vigencia_hasta):  
27 - raise ValueError("El precio seleccionado no se encuentra dentro de las fechas permitidas.")  
28 -  
29 - result_palabra = (sellos + palabras) * precio  
30 - result_ejemplar = (copias * precio_ejemplar) + (publicar * precio_ejemplar)  
31 -  
32 - if organismo:  
33 - resultado = result_ejemplar + result_palabra / 2  
34 - else:  
35 - resultado = result_ejemplar + result_palabra  
36 -  
37 - precio_resultado = ComprobantePago(edicto=edicto, resultado=resultado)  
38 - precio_resultado.save()  
39 - return precio_resultado 3 +from datetime import datetime, time
  4 +
  5 +
  6 +def calculadora(edicto, precio):
  7 + try:
  8 + with transaction.atomic():
  9 + organismo = edicto.usuario.organismo
  10 + es_publico = organismo.es_publico if organismo else False
  11 + sellos = edicto.cantidad_sellos
  12 + palabras = edicto.cantidad_palabras
  13 + copias = edicto.cantidad_copias
  14 + publicar = edicto.dias_publicar
  15 + precio_valores = {
  16 + 'precio_palabra': precio.precio,
  17 + 'precio_ejemplar': precio.precio_ejemplar,
  18 + 'vigencia_desde': precio.vigencia_desde,
  19 + 'vigencia_hasta': precio.vigencia_hasta,
  20 + }
  21 + current_datetime = timezone.now().replace(tzinfo=None)
  22 + vigencia_desde = datetime.combine(precio_valores['vigencia_desde'], time.min)
  23 + vigencia_hasta = datetime.combine(precio_valores['vigencia_hasta'], time.max)
  24 + if not (vigencia_desde <= current_datetime <= vigencia_hasta):
  25 + raise ValueError("El precio seleccionado no se encuentra dentro de las fechas permitidas.")
  26 +
  27 + result_palabra = (sellos + palabras) * precio_valores['precio']
  28 + result_ejemplar = \
  29 + (copias * precio_valores['precio_ejemplar']) + (publicar * precio_valores['precio_ejemplar'])
  30 +
  31 + if es_publico:
  32 + resultado = result_ejemplar + result_palabra / 2
  33 + else:
  34 + resultado = result_ejemplar + result_palabra
  35 +
  36 + return resultado
  37 + except ValueError as values:
  38 +
  39 + raise ValueError("Los valores proporcionados son incorrectos: " + str(values))
@@ -3,7 +3,7 @@ from rest_framework import serializers @@ -3,7 +3,7 @@ from rest_framework import serializers
3 3
4 from .constants import EXTENSIONES_VALIDAS 4 from .constants import EXTENSIONES_VALIDAS
5 5
6 -from .models import Edicto, Precio 6 +from .models import Edicto, Precio, ComprobantePago
7 from usuario.serializers import UsuarioListaSerializer 7 from usuario.serializers import UsuarioListaSerializer
8 8
9 9
@@ -51,7 +51,7 @@ class PrecioSerializer(serializers.ModelSerializer): @@ -51,7 +51,7 @@ class PrecioSerializer(serializers.ModelSerializer):
51 model = Precio 51 model = Precio
52 fields = ('usuario', 52 fields = ('usuario',
53 'moneda', 53 'moneda',
54 - 'precio', 54 + 'precio_palabra',
55 'precio_ejemplar', 55 'precio_ejemplar',
56 'vigencia_desde', 56 'vigencia_desde',
57 'vigencia_hasta', 57 'vigencia_hasta',
@@ -59,4 +59,39 @@ class PrecioSerializer(serializers.ModelSerializer): @@ -59,4 +59,39 @@ class PrecioSerializer(serializers.ModelSerializer):
59 59
60 included_serializers = { 60 included_serializers = {
61 'usuario': UsuarioListaSerializer 61 'usuario': UsuarioListaSerializer
  62 + }
  63 +
  64 +
  65 +class PagoSerializer(serializers.ModelSerializer):
  66 + class Meta:
  67 + model = ComprobantePago
  68 + fields = ('monto',
  69 + 'edicto',
  70 + )
  71 + read_only_fields = ('monto', )
  72 +
  73 + included_serializers = {
  74 + 'edicto': EdictoSerializer,
  75 + }
  76 +
  77 + def validate(self, data):
  78 + edicto = data.get('edicto')
  79 + if edicto and edicto.estado != 'pendiente_de_pago':
  80 + raise serializers.ValidationError(
  81 + "El edicto debe estar en estado 'pendiente de pago' para visualizar el monto a pagar.")
  82 +
  83 + return data
  84 +
  85 +
  86 +class ComprobanteSerializer(serializers.ModelSerializer):
  87 +
  88 + class Meta:
  89 + model = ComprobantePago
  90 + fields = ('numero_comprobante',
  91 + 'fecha_pago',
  92 + )
  93 +
  94 + included_serializers = {
  95 + 'edicto': EdictoSerializer,
  96 + 'monto': 'monto.serializers.PagoSerialzer',
62 } 97 }
@@ -2,7 +2,7 @@ from rest_framework import routers @@ -2,7 +2,7 @@ from rest_framework import routers
2 2
3 from organismo import api as organismo_api 3 from organismo import api as organismo_api
4 from usuario import api as usuario_api 4 from usuario import api as usuario_api
5 -from edicto.api import EdictoViewSet 5 +from edicto.api import EdictoViewSet, ComprobanteViewSets
6 from edicto import api as edicto_api 6 from edicto import api as edicto_api
7 # Define routes 7 # Define routes
8 router = routers.DefaultRouter() 8 router = routers.DefaultRouter()
@@ -11,5 +11,7 @@ router.register(prefix='usuario', viewset=usuario_api.UsuarioViewSet) @@ -11,5 +11,7 @@ router.register(prefix='usuario', viewset=usuario_api.UsuarioViewSet)
11 router.register(prefix='organismo', viewset=organismo_api.OrganismoViewSet) 11 router.register(prefix='organismo', viewset=organismo_api.OrganismoViewSet)
12 router.register(r'edicto', EdictoViewSet, basename='edicto') 12 router.register(r'edicto', EdictoViewSet, basename='edicto')
13 router.register(prefix='precio', viewset=edicto_api.PrecioViewSet) 13 router.register(prefix='precio', viewset=edicto_api.PrecioViewSet)
  14 +router.register(prefix='pago', viewset=edicto_api.PagoViewSets)
  15 +router.register(r'comprobante', ComprobanteViewSets, basename='comprobante')
14 16
15 17