🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 6 Min Lesezeit
0

Contabilidad para Django Developers: Implementando Asientos Contables

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




Introducción



Como desarrollador de Django, ¿alguna vez te has enfrentado al desafío de implementar un sistema contable y te has sentido abrumado por la terminología y los conceptos? No estás solo. La contabilidad puede parecer un mundo completamente diferente, pero en realidad tiene muchas similitudes con la programación.



Este tutorial te guiará paso a paso en la implementación de un sistema de asientos contables en Django, utilizando analogías familiares para desarrolladores. Aprenderás a manejar diferentes tipos de asientos contables (apertura, operativos, ajustes y cierre) de una manera que tenga sentido para tu mente de programador.



Al final de este tutorial, serás capaz de implementar un sistema contable robusto utilizando solo el admin de Django, con validaciones sólidas y pruebas automatizadas.






Prerrequisitos




  • Python 3.12

  • Django 5.0+

  • Conocimientos básicos de modelos en Django

  • Familiaridad con el admin de Django






Conceptos Clave






Asientos Contables = Transacciones en Base de Datos



Piensa en los asientos contables como transacciones en una base de datos:





  • Asiento de Apertura: Es como el initial migration de tus modelos


  • Asientos Operativos: Similar a los CRUD operations diarios


  • Asientos de Ajuste: Como un database cleanup script


  • Asientos de Cierre: Equivalente a un end-of-period backup






Implementación de Modelos






CODE
from django.db import models
from django.core.exceptions import ValidationError
from django.db.models import Sum
from decimal import Decimal
from enum import Enum
import datetime

class AsientoTipo(models.TextChoices):
APERTURA = 'AP', 'Apertura'
OPERATIVO = 'OP', 'Operativo'
AJUSTE = 'AJ', 'Ajuste'
CIERRE = 'CI', 'Cierre'

class Cuenta(models.Model):
codigo = models.CharField(max_length=20, unique=True)
nombre = models.CharField(max_length=100)
es_deudora = models.BooleanField(
help_text="True para cuentas que aumentan con débito"
)

def __str__(self):
return f"{self.codigo} - {self.nombre}"

class Meta:
ordering = ['codigo']

class LibroContable(models.Model):
año = models.PositiveIntegerField()
esta_cerrado = models.BooleanField(default=False)

class Meta:
unique_together = ['año']

def clean(self):
if self.esta_cerrado:
if Asiento.objects.filter(
libro=self,
tipo=AsientoTipo.CIERRE
).count() == 0:
raise ValidationError(
"No se puede cerrar un libro sin asiento de cierre"
)

def __str__(self):
return f"Libro Contable {self.año}"

class Asiento(models.Model):
libro = models.ForeignKey(LibroContable, on_delete=models.PROTECT)
fecha = models.DateField()
tipo = models.CharField(
max_length=2,
choices=AsientoTipo.choices,
default=AsientoTipo.OPERATIVO
)
descripcion = models.TextField()

def clean(self):
self._validar_fecha()
self._validar_tipo_asiento()
self._validar_balance()

def _validar_fecha(self):
if self.fecha.year != self.libro.año:
raise ValidationError(
"La fecha debe corresponder al año del libro contable"
)

def _validar_tipo_asiento(self):
if self.tipo == AsientoTipo.APERTURA:
self._validar_apertura()
elif self.tipo == AsientoTipo.CIERRE:
self._validar_cierre()

def _validar_apertura(self):
if Asiento.objects.filter(
libro=self.libro,
tipo=AsientoTipo.APERTURA
).exclude(pk=self.pk).exists():
raise ValidationError(
"Ya existe un asiento de apertura para este libro"
)

def _validar_cierre(self):
if Asiento.objects.filter(
libro=self.libro,
tipo=AsientoTipo.CIERRE
).exclude(pk=self.pk).exists():
raise ValidationError(
"Ya existe un asiento de cierre para este libro"
)

def _validar_balance(self):
if hasattr(self, 'pk'):
total_debe = Decimal('0')
total_haber = Decimal('0')
for detalle in self.detalles.all():
total_debe += detalle.debe
total_haber += detalle.haber
if total_debe != total_haber:
raise ValidationError(
"El asiento debe estar balanceado (debe = haber)"
)

def __str__(self):
return f"{self.fecha} - {self.get_tipo_display()} - {self.descripcion[:50]}"

class DetalleAsiento(models.Model):
asiento = models.ForeignKey(
Asiento,
related_name='detalles',
on_delete=models.CASCADE
)
cuenta = models.ForeignKey(Cuenta, on_delete=models.PROTECT)
debe = models.DecimalField(
max_digits=15,
decimal_places=2,
default=0
)
haber = models.DecimalField(
max_digits=15,
decimal_places=2,
default=0
)

def clean(self):
if self.debe > 0 and self.haber > 0:
raise ValidationError(
"Un movimiento no puede tener debe y haber simultáneamente"
)
if self.debe == 0 and self.haber == 0:
raise ValidationError(
"El movimiento debe tener un valor en debe o haber"
)

class Meta:
ordering = ['id']









Configuración del Admin






CODE
from django.contrib import admin
from django.db import models
from django.forms import ModelForm
from .models import LibroContable, Cuenta, Asiento, DetalleAsiento

class DetalleAsientoInline(admin.TabularInline):
model = DetalleAsiento
extra = 2
min_num = 2

@admin.register(Asiento)
class AsientoAdmin(admin.ModelAdmin):
list_display = ['fecha', 'tipo', 'descripcion', 'total_debe', 'total_haber']
list_filter = ['tipo', 'libro']
search_fields = ['descripcion']
inlines = [DetalleAsientoInline]

def total_debe(self, obj):
return obj.detalles.aggregate(
total=models.Sum('debe')
)['total'] or 0

def total_haber(self, obj):
return obj.detalles.aggregate(
total=models.Sum('haber')
)['total'] or 0

@admin.register(Cuenta)
class CuentaAdmin(admin.ModelAdmin):
list_display = ['codigo', 'nombre', 'es_deudora']
search_fields = ['codigo', 'nombre']

@admin.register(LibroContable)
class LibroContableAdmin(admin.ModelAdmin):
list_display = ['año', 'esta_cerrado']
list_filter = ['esta_cerrado']









Tests Automatizados






CODE
from django.test import TestCase
from django.core.exceptions import ValidationError
from decimal import Decimal
from .models import LibroContable, Cuenta, Asiento, DetalleAsiento

class AsientoTests(TestCase):
def setUp(self):
self.libro = LibroContable.objects.create(año=2024)
self.cuenta_caja = Cuenta.objects.create(
codigo='1.1.1',
nombre='Caja',
es_deudora=True
)
self.cuenta_capital = Cuenta.objects.create(
codigo='3.1.1',
nombre='Capital',
es_deudora=False
)

def test_asiento_apertura(self):
asiento = Asiento.objects.create(
libro=self.libro,
fecha='2024-01-01',
tipo=AsientoTipo.APERTURA,
descripcion='Asiento de apertura'
)

DetalleAsiento.objects.create(
asiento=asiento,
cuenta=self.cuenta_caja,
debe=Decimal('1000')
)

DetalleAsiento.objects.create(
asiento=asiento,
cuenta=self.cuenta_capital,
haber=Decimal('1000')
)

asiento.full_clean() # Debería validar sin errores

# Intentar crear otro asiento de apertura
with self.assertRaises(ValidationError):
Asiento.objects.create(
libro=self.libro,
fecha='2024-01-01',
tipo=AsientoTipo.APERTURA,
descripcion='Segundo asiento de apertura'
).full_clean()









Ejemplo Real: Sistema de Transferencias






CODE
def realizar_transferencia(
libro_id: int,
fecha: str,
cuenta_origen_id: int,
cuenta_destino_id: int,
monto: Decimal,
descripcion: str
) -> Asiento:
"""
Crea un asiento contable para una transferencia entre cuentas.
"""
libro = LibroContable.objects.get(pk=libro_id)

asiento = Asiento.objects.create(
libro=libro,
fecha=fecha,
tipo=AsientoTipo.OPERATIVO,
descripcion=descripcion
)

# Movimiento de salida
DetalleAsiento.objects.create(
asiento=asiento,
cuenta_id=cuenta_origen_id,
haber=monto
)

# Movimiento de entrada
DetalleAsiento.objects.create(
asiento=asiento,
cuenta_id=cuenta_destino_id,
debe=monto
)

asiento.full_clean()
return asiento









Mejores Prácticas





  1. Validaciones de Seguridad




    • Implementar permisos por tipo de asiento

    • Validar fechas y períodos contables

    • Prevenir modificaciones en libros cerrados




  2. Manejo de Errores




    • Usar transacciones para operaciones atómicas

    • Implementar rollback en caso de error

    • Registrar auditoría de cambios




  3. Patrones de Diseño




    • Usar Factory Method para diferentes tipos de asientos

    • Implementar Observer para notificaciones

    • Aplicar Strategy para diferentes reglas contables








Conclusión



Has aprendido a implementar un sistema contable básico pero robusto en Django, utilizando solo el admin. Los conceptos clave que debes recordar son:




  • Los asientos contables son como transacciones en una base de datos

  • Las validaciones son cruciales para mantener la integridad de los datos

  • El admin de Django es suficiente para muchas operaciones contables

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
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
Windows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC
1 Quelle
Vorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Contabilidad para Django Developers: Implementando Asientos 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 ...