Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Podcasts & Audio Briefings9to5Google: The Sideload 046: Frictionmaxxing with Allison Johnson(29.09.2026 um 22:31 Uhr)
•
YouTube Security VideosNASA's SpaceX Crew-13 Prelaunch News Conference (Sept. 30, 2026)(22.09.2026 um 22:14 Uhr)
•
YouTube Security VideosNASA's SpaceX Crew-13 Launch(29.09.2026 um 00:25 Uhr)
•
Windows Tipps & SecurityMicrosoft Releases WSL Containers for Windows 11(29.09.2026 um 22:37 Uhr)
•
Unix & Linux ServerSecurity: Mangelnde Rechteprüfung in KDE Plasma (Ubuntu)(29.09.2026 um 23:50 Uhr)
•
Unix & Linux ServerSecurity: Mehrere Probleme in amazon-cloudwatch-agent (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Pufferüberlauf in corosync (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Ausführen beliebiger Kommandos in perl-DBI (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Zwei Probleme in cjose (SUSE)(30.09.2026 um 00:10 Uhr)
••
Podcasts & Audio Briefings9to5Google: The Sideload 046: Frictionmaxxing with Allison Johnson(29.09.2026 um 22:31 Uhr)
•
YouTube Security VideosNASA's SpaceX Crew-13 Prelaunch News Conference (Sept. 30, 2026)(22.09.2026 um 22:14 Uhr)
•
YouTube Security VideosNASA's SpaceX Crew-13 Launch(29.09.2026 um 00:25 Uhr)
•
Windows Tipps & SecurityMicrosoft Releases WSL Containers for Windows 11(29.09.2026 um 22:37 Uhr)
•
Unix & Linux ServerSecurity: Mangelnde Rechteprüfung in KDE Plasma (Ubuntu)(29.09.2026 um 23:50 Uhr)
•
Unix & Linux ServerSecurity: Mehrere Probleme in amazon-cloudwatch-agent (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Pufferüberlauf in corosync (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Ausführen beliebiger Kommandos in perl-DBI (SUSE)(29.09.2026 um 23:54 Uhr)
•
Unix & Linux ServerSecurity: Zwei Probleme in cjose (SUSE)(30.09.2026 um 00:10 Uhr)
••
Intelligence View
⚡ tsecurity.de Intelligence

Contabilidad para Django Developers: Períodos Contables 🔧

Introducción Como desarrollador, probablemente has implementado sistemas donde el tiempo es crucial: logs con timestamps, fechas de creación/modificación, o incluso sistemas de caché. Los períodos contables son similares, pero con una par…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




Introducción



Como desarrollador, probablemente has implementado sistemas donde el tiempo es crucial: logs con timestamps, fechas de creación/modificación, o incluso sistemas de caché. Los períodos contables son similares, pero con una particularidad: son la columna vertebral de cualquier sistema financiero serio.



¿Has intentado alguna vez modificar un registro financiero del mes pasado y te has preguntado por qué tu contador puso el grito en el cielo? En este tutorial, aprenderás por qué, y más importante aún, cómo implementar un sistema robusto de períodos contables en Django.



Al finalizar este tutorial, serás capaz de:




  • Implementar períodos contables seguros en Django

  • Proteger la integridad de los datos financieros

  • Utilizar el admin de Django para gestionar períodos contables






Prerrequisitos




  • Python 3.8+

  • Django 5.0+

  • Conocimientos básicos de modelos Django

  • SQLite o PostgreSQL






Conceptos Clave






Período Contable: El Transaction Commit de la Contabilidad



Piensa en un período contable como un git commit o una transacción de base de datos: una vez "committed", no deberías modificarlo. En contabilidad, esto se conoce como "cerrar un período", y es tan crítico como hacer un commit en producción.






Estados de un Período



Similar a los estados de un proceso en un sistema operativo:




  • DRAFT (borrador): Como una rama de desarrollo

  • ACTIVE (activo): Como la rama principal

  • CLOSED (cerrado): Como un tag de versión






Implementación






Modelos Base






from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone
from datetime import datetime, timedelta
from django.contrib import admin
from django.utils.translation import gettext_lazy as _

class AccountingPeriod(models.Model):
STATUS_CHOICES = [
('DRAFT', 'Borrador'),
('ACTIVE', 'Activo'),
('CLOSED', 'Cerrado'),
]

name = models.CharField(
max_length=100,
unique=True,
help_text="Ejemplo: 'Enero 2024'"
)
start_date = models.DateField()
end_date = models.DateField()
status = models.CharField(
max_length=10,
choices=STATUS_CHOICES,
default='DRAFT'
)
created_at = models.DateTimeField(auto_now_add=True)
closed_at = models.DateTimeField(null=True, blank=True)

class Meta:
ordering = ['-start_date']
constraints = [
models.CheckConstraint(
check=models.Q(end_date__gte=models.F('start_date')),
name='end_date_after_start_date'
)
]

def clean(self):
if not self.pk: # Solo para nuevos períodos
self.validate_no_overlapping()

if self.status == 'CLOSED' and not self.closed_at:
self.closed_at = timezone.now()

def validate_no_overlapping(self):
overlapping = AccountingPeriod.objects.filter(
models.Q(start_date__lte=self.end_date) &
models.Q(end_date__gte=self.start_date)
)
if overlapping.exists():
raise ValidationError(
'El período se superpone con períodos existentes.'
)

def close_period(self):
if self.status != 'ACTIVE':
raise ValidationError(
'Solo se pueden cerrar períodos activos.'
)
self.status = 'CLOSED'
self.closed_at = timezone.now()
self.save()

def activate_period(self):
if self.status != 'DRAFT':
raise ValidationError(
'Solo se pueden activar períodos en borrador.'
)
self.status = 'ACTIVE'
self.save()

def __str__(self):
return f"{self.name} ({self.get_status_display()})"

class AccountingEntry(models.Model):
period = models.ForeignKey(
AccountingPeriod,
on_delete=models.PROTECT,
related_name='entries'
)
date = models.DateField()
description = models.CharField(max_length=200)
amount = models.DecimalField(
max_digits=10,
decimal_places=2
)
created_at = models.DateTimeField(auto_now_add=True)

def clean(self):
if not self.period_id:
self.period = self.get_appropriate_period()

if self.period.status == 'CLOSED':
raise ValidationError(
'No se pueden crear entradas en períodos cerrados.'
)

if not (self.period.start_date <= self.date <= self.period.end_date):
raise ValidationError(
'La fecha debe estar dentro del período contable.'
)

def get_appropriate_period(self):
period = AccountingPeriod.objects.filter(
start_date__lte=self.date,
end_date__gte=self.date,
status='ACTIVE'
).first()

if not period:
raise ValidationError(
'No existe un período activo para la fecha especificada.'
)
return period

def __str__(self):
return f"{self.date} - {self.description} (${self.amount})"









Configuración del Admin






from django.contrib import admin
from django.utils.html import format_html

@admin.register(AccountingPeriod)
class AccountingPeriodAdmin(admin.ModelAdmin):
list_display = ['name', 'start_date', 'end_date', 'status_badge',
'created_at']
list_filter = ['status']
search_fields = ['name']
readonly_fields = ['closed_at']

def status_badge(self, obj):
colors = {
'DRAFT': 'gray',
'ACTIVE': 'green',
'CLOSED': 'red',
}
return format_html(
'<span style="color: {};">{}</span>',
colors[obj.status],
obj.get_status_display()
)

status_badge.short_description = 'Estado'

def get_readonly_fields(self, request, obj=None):
if obj and obj.status == 'CLOSED':
return ['name', 'start_date', 'end_date', 'status', 'closed_at']
return self.readonly_fields

actions = ['activate_periods', 'close_periods']

def activate_periods(self, request, queryset):
for period in queryset:
try:
period.activate_period()
except ValidationError as e:
self.message_user(
request,
f"Error al activar {period.name}: {str(e)}",
level='ERROR'
)
activate_periods.short_description = "Activar períodos seleccionados"

def close_periods(self, request, queryset):
for period in queryset:
try:
period.close_period()
except ValidationError as e:
self.message_user(
request,
f"Error al cerrar {period.name}: {str(e)}",
level='ERROR'
)
close_periods.short_description = "Cerrar períodos seleccionados"

@admin.register(AccountingEntry)
class AccountingEntryAdmin(admin.ModelAdmin):
list_display = ['date', 'description', 'amount', 'period']
list_filter = ['period', 'date']
search_fields = ['description']

def get_readonly_fields(self, request, obj=None):
if obj and obj.period.status == 'CLOSED':
return ['date', 'description', 'amount', 'period']
return []

def has_delete_permission(self, request, obj=None):
if obj and obj.period.status == 'CLOSED':
return False
return super().has_delete_permission(request, obj)









Tests






from django.test import TestCase
from django.core.exceptions import ValidationError
from datetime import date, timedelta
from .models import AccountingPeriod, AccountingEntry

class AccountingPeriodTests(TestCase):
def setUp(self):
self.period = AccountingPeriod.objects.create(
name="Test Period",
start_date=date(2024, 1, 1),
end_date=date(2024, 1, 31),
status='DRAFT'
)

def test_period_activation(self):
self.period.activate_period()
self.assertEqual(self.period.status, 'ACTIVE')

def test_period_closure(self):
self.period.activate_period()
self.period.close_period()
self.assertEqual(self.period.status, 'CLOSED')

def test_overlapping_periods(self):
with self.assertRaises(ValidationError):
AccountingPeriod.objects.create(
name="Overlapping Period",
start_date=date(2024, 1, 15),
end_date=date(2024, 2, 15),
status='DRAFT'
)

class AccountingEntryTests(TestCase):
def setUp(self):
self.period = AccountingPeriod.objects.create(
name="Test Period",
start_date=date(2024, 1, 1),
end_date=date(2024, 1, 31),
status='ACTIVE'
)

def test_entry_creation(self):
entry = AccountingEntry.objects.create(
period=self.period,
date=date(2024, 1, 15),
description="Test Entry",
amount=100.00
)
self.assertEqual(entry.period, self.period)

def test_entry_in_closed_period(self):
self.period.close_period()
with self.assertRaises(ValidationError):
AccountingEntry.objects.create(
period=self.period,
date=date(2024, 1, 15),
description="Test Entry",
amount=100.00
)









Mejores Prácticas





  1. Validaciones de Seguridad




    • Usar PROTECT en las foreign keys para evitar eliminación accidental

    • Implementar validaciones a nivel de modelo

    • Usar el sistema de permisos de Django




  2. Manejo de Errores




    • Validaciones descriptivas

    • Mensajes de error claros

    • Logging de operaciones críticas




  3. Patrones de Diseño




    • State Pattern para estados del período

    • Factory Method para crear entradas

    • Observer Pattern para auditoría








Conclusión



Has aprendido a implementar un sistema robusto de períodos contables en Django que:




  • Protege la integridad de los datos financieros

  • Implementa validaciones de negocio

  • Utiliza el admin de Django eficientemente

2. Cyber Threat Intelligence & Forensik

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Contabilidad para Django Developers: Períodos Contables 🔧

Thematisch verwandte Begriffe: Contabilidad, para, Django, Developers · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-102253 | iperf3 versions prior to 3.22 contains a denial of service vulnerabilit…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag