🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 6 Min Lesezeit
0

Contabilidad para Django Developers: Períodos Contables 🔧

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




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






CODE
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






CODE
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






CODE
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

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ä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 ...