This commit is contained in:
root
2025-12-21 15:14:34 -06:00
commit c04ee70afc
40 changed files with 3048 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@@ -0,0 +1,19 @@
*.log
*.pot
*.pyc
*.bak
*.bk
*.xlsx
*.pdf
db.sqlite3
__pycache__/
staticfiles
media
**/migrations/*
/modeler/.config
outputs/
bin/
include/
lib/

0
catalogos/__init__.py Executable file
View File

56
catalogos/admin.py Executable file
View File

@@ -0,0 +1,56 @@
from django.contrib import admin
# Register your models here.
from .models import Banco, Condominio, PeriodoCorte, CuentaContable
#from condominio_san_rafael.procesos import run_acum_san_rafael
#from condominio_santa_maria.procesos import run_acum_santa_maria
@admin.register(CuentaContable)
class CuentaContableAdmin(admin.ModelAdmin):
list_display = ('num_cuenta', 'descripcion')
list_filter = ('num_cuenta',)
@admin.register(Banco)
class BancoAdmin(admin.ModelAdmin):
list_display = ('clave', 'descripcion')
@admin.register(Condominio)
class CondominioAdmin(admin.ModelAdmin):
list_display = ('nombre', 'calle', 'colonia', 'delegacion', 'correo_electronico')
@admin.register(PeriodoCorte)
class PeriodoAdmin(admin.ModelAdmin):
list_display = ('condominio', 'fecha_inicial', 'fecha_final', 'saldo_final')
actions = ['acumulados', 'loadfile']
def acumulados(self, request, queryset):
for obj in queryset:
# field_value = getattr(obj, 'condominio')
print(" genera acumulados %s " % obj.condominio)
shortname = "%s" % obj.condominio
if shortname == "SANRAFAEL":
#run_acum_san_rafael(obj.condominio, shortname)
pass
elif shortname == "SANTAMARIA":
#run_acum_santa_maria(obj.condominio, shortname)
pass
self.message_user(request, " Fin del proceso de generacion de acumulados ")
acumulados.short_description = "Obtiene acumulados"
def loadfile(self, request, queryset):
for obj in queryset:
# field_value = getattr(obj, 'condominio')
#print(" genera acumulados %s " % obj.condominio)
condominio = "%s" % obj.condominio
print(condominio)
break
#self.message_user(request, " Fin del proceso de actualizacion de cuotas ")
loadfile.short_description = "Carga de archivo con movimientos"

5
catalogos/apps.py Executable file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CatalogosConfig(AppConfig):
name = 'catalogos'

67
catalogos/models.py Executable file
View File

@@ -0,0 +1,67 @@
from django.db import models
# Create your models here.
class Banco(models.Model):
clave = models.CharField(max_length=3)
descripcion = models.CharField(max_length=25, blank=True, null=True)
def __str__(self):
return '%s %s' % (self.clave, self.descripcion)
class Meta:
managed = True
db_table = 'banco'
class Condominio(models.Model):
nombre = models.CharField(max_length=45)
calle = models.CharField(max_length=45, blank=True, null=True)
colonia = models.CharField(max_length=45, blank=True, null=True)
delegacion = models.CharField(max_length=45, blank=True, null=True)
ciudad = models.CharField(max_length=45, blank=True, null=True)
estado = models.CharField(max_length=45, blank=True, null=True)
cp = models.CharField(max_length=5, blank=True, null=True)
regimen = models.CharField(max_length=45, blank=True, null=True)
rfc = models.CharField(max_length=13, blank=True, null=True)
fecha_constitucion = models.DateField(blank=True, null=True)
correo_electronico = models.CharField(max_length=254, null=True)
def __str__(self):
return '%s' % (self.nombre)
class Meta:
managed = True
db_table = 'condominio'
verbose_name_plural = "Condominios"
class PeriodoCorte(models.Model):
condominio = models.ForeignKey(Condominio, on_delete=models.PROTECT)
fecha_inicial = models.DateField(blank=True, null=True)
saldo_inicial = models.DecimalField(max_digits=12, decimal_places=2, default=0, null=True)
fecha_final = models.DateField(blank=True, null=True)
saldo_final = models.DecimalField(max_digits=12, decimal_places=2, default=0, null=True)
def __str__(self):
return '%s' % (self.condominio)
class Meta:
managed = True
db_table = 'periodo_corte'
verbose_name_plural = "Procesos y fechas de corte"
class CuentaContable(models.Model):
num_cuenta = models.CharField(max_length=20)
descripcion = models.CharField(max_length=100)
clave_mayor = models.CharField(max_length=4)
def __str__(self):
return '%s %s' % (self.num_cuenta, self.descripcion)
class Meta:
managed = True
db_table = 'cuenta_contable'
ordering = ['num_cuenta']
verbose_name_plural = "Cuentas contables"

3
catalogos/tests.py Executable file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

5
catalogos/views.py Executable file
View File

@@ -0,0 +1,5 @@
from django.http import HttpResponseRedirect
def home(request):
return HttpResponseRedirect('/5up3rc4l1fr4ct1c03sp1r4l1d0s0')

0
ciec/__init__.py Executable file
View File

16
ciec/asgi.py Executable file
View File

@@ -0,0 +1,16 @@
"""
ASGI config for ciec project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ciec.settings')
application = get_asgi_application()

43
ciec/procesos.py Executable file
View File

@@ -0,0 +1,43 @@
from django.db import transaction
from django.db import connection
from datetime import datetime, timedelta
#from explorer.models import Query
def dictfetchall(cursor):
desc = cursor.description
if desc:
return [
dict(zip([col[0] for col in desc],row))
for row in cursor.fetchall()
]
else:
return None
def execsql(consulta):
cursor = connection.cursor()
#print(consulta)
cursor.execute(consulta)
result_list = dictfetchall(cursor)
cursor.close()
return result_list
def styles_workbook(workbook):
#workbook = writer.book
#styles = []
style = {}
style['titulos'] = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter'})
style['celdas'] = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
style['bordes'] = workbook.add_format({'bottom': 1})
style['descripcion'] = workbook.add_format({'align': 'left', 'valign': 'vjustify'})
style['numeros'] = workbook.add_format({'num_format': '#,##0.00', 'valign': 'vcenter'})
style['fechas'] = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'dd/mmm/yyyy' })
style['cabecera'] = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top', 'align' : 'center', 'fg_color': '#D7E4BC', 'border': 1})
style['condicion1'] = workbook.add_format({'bold': True, 'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
style['condicion2'] = workbook.add_format({'bold': True, 'bg_color': '#C6EFCE', 'font_color': '#006100'})
style['ocultar'] = workbook.add_format({'font_color': '#FFFFFF'})
#styles.append(style)
return style

152
ciec/settings.py Executable file
View File

@@ -0,0 +1,152 @@
"""
Django settings for ciec project.
Generated by 'django-admin startproject' using Django 4.2.20.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-t&8&t7$9(#9jni(4yva_2=x&#gz#@s7nx&lwv132he$6_p4d7%'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'catalogos',
'condominio_aragon_37',
'condominio_balcones',
'condominio_coyoacan',
'condominio_sadicarnot81_Nvo',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
]
ROOT_URLCONF = 'ciec.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates/')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.csrf',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'ciec.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'mejia1963',
#'HOST': '172.17.0.2',
'HOST': '10.6.0.2',
'PORT': '5432',
}
}
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'es-MX'
TIME_ZONE = 'America/Mexico_City'
USE_I18N = True
USE_L10N = True
USE_TZ = True
NUMBER_GROUPING = (3,2,0)
USE_DECIMAL_SEPARATOR = True
DECIMAL_SEPARATOR = '.'
USE_THOUSAND_SEPARATOR = True
THOUSAND_SEPARATOR = ','
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

22
ciec/urls.py Executable file
View File

@@ -0,0 +1,22 @@
from django.contrib import admin
#from django.conf.urls import url
from django.urls import path, include, re_path
from django.conf import settings
from catalogos.views import home
#from django.utils.functional import curry
from django.views.defaults import server_error, page_not_found
from django.conf.urls.static import static
from functools import partial as curry
admin.site.site_header = "CIEC Cuotas, Ingresos y Egresos Condominales"
admin.site.site_title = "CIEC"
admin.site.index_title = "Administración"
handler500 = curry(server_error, template_name='admin/500.html')
handler404 = curry(page_not_found, template_name='admin/404.html')
urlpatterns = [
re_path(r'^$', home, name='home'),
re_path(r'^5up3rc4l1fr4ct1c03sp1r4l1d0s0/', admin.site.urls, name = 'admin'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

16
ciec/wsgi.py Executable file
View File

@@ -0,0 +1,16 @@
"""
WSGI config for ciec project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ciec.settings')
application = get_wsgi_application()

View File

206
condominio_aragon_37/admin.py Executable file
View File

@@ -0,0 +1,206 @@
from django.contrib import admin
from .models import Movimiento, DetalleMovimiento, CuentaBanco, CuotasCondominio, Condomino, AcumuladoMes, Registro, MovSinIdent, Asiento
from .procesos import run_determinacionSaldos_aragon37, run_estado_cuenta, run_detalle_ingresos_egresos
from django.utils.safestring import mark_safe
from io import BytesIO
from django.http import HttpResponse
# Register your models here.
class DetalleMovtoInline(admin.TabularInline):
model = DetalleMovimiento
fields = ['cuenta_contable', 'monto', 'comentario']
def get_extra(self, request, obj=None, **kwargs):
extra = 4
return extra
@admin.register(Movimiento)
class MovtoAdmin(admin.ModelAdmin):
list_display = ('id','fecha_movimiento','descripcion','retiros','depositos','condomino','conciliacion')
search_fields = ('descripcion',)
date_hierarchy = 'fecha_movimiento'
ordering = ('-fecha_movimiento',)
save_on_top = True
inlines = [DetalleMovtoInline]
def retiros(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiro)
def depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.deposito)
def conciliacion(self, request, obj=None, **kwargs):
cantidades = DetalleMovimiento.objects.filter(movimiento_id=request.id).values_list('monto', flat=True)
total = sum(cantidades)
if (total != (request.retiro + request.deposito)):
return False
else:
return True
conciliacion.boolean = True
@admin.register(CuentaBanco)
class CuentaBancoAdmin(admin.ModelAdmin):
list_display = ('banco','clabe','apoderado')
@admin.register(CuotasCondominio)
class CuotasAdmin(admin.ModelAdmin):
list_display = ('descripcion', 'mes_inicial', 'mes_final', 'cantidad','cuenta_contable')
ordering = ('-mes_inicial',)
def cantidad(self, request, obj=None, **kwargs):
return "{:,}".format(request.monto)
@admin.register(Condomino)
class CondominoAdmin(admin.ModelAdmin):
list_display = ('depto', 'poseedor', 'adeudo_inicio', 'cuotas', 'depositos', 'adeudo_actual')
search_fields = ('depto', 'propietario', 'poseedor')
#actions = ['determina_saldos']
actions = ['determina_saldos', 'reporte_individual']
def adeudo_inicio(self, request, obj=None, **kwargs):
return "{:,}".format(request.adeudo_inicial)
def cuotas(self, request, obj=None, **kwargs):
cargos = request.cargos - request.adeudo_inicial
return "{:,}".format(cargos)
def depositos(self, request, obj=None, **kwargs):
pagos = request.abonos
return "{:,}".format(pagos)
def adeudo_actual(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def determina_saldos(self, request, queryset):
for obj in queryset:
# print(" determina saldos %s " % obj.depto)
run_determinacionSaldos_aragon37(obj)
#pass
self.message_user(request, " Fin del proceso de determinacion de saldos ")
def reporte_individual(self, request, queryset):
condominos = []
for obj in queryset:
item = {}
item['id'] = obj.id
item['depto'] = obj.depto
item['poseedor'] = obj.poseedor
item['adeudo'] = obj.saldo
condominos.append(item)
#print(condominos)
filename = 'ciec_output_ec.xlsx'
stream = BytesIO()
data = run_estado_cuenta(condominos, stream)
self.message_user(request, "Fin del proceso, verifique area de descargas ")
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
response.write(data)
return response
reporte_individual.short_description = "Descarga estado de cuenta"
determina_saldos.short_description = "Determinacion de Saldos"
@admin.register(AcumuladoMes)
class AcumuladoAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'mes', 'fecha_inicial', 'fecha_final', 'Depositado', 'Retirado', 'Saldos')
ordering = ('-fecha_inicial', 'cuenta_banco',)
actions = ['detalle_ing_egr']
#actions = ['export_as_csv']
#change_list_template = "admin/titulo_acumulados.html"
def Depositado(self, request, obj=None, **kwargs):
return "{:,}".format(request.depositos)
def Retirado(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiros)
def Saldos(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def detalle_ing_egr(self, request, queryset):
dates = []
for obj in queryset:
dates.append(obj.fecha_inicial)
dates.append(obj.fecha_final)
filename = 'ciec_output_ie.xlsx'
stream = BytesIO()
data = run_detalle_ingresos_egresos(min(dates), max(dates), stream)
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
response.write(data)
return(response)
detalle_ing_egr.short_description = "Descargar detalle de ingresos y egresos"
class dontLog:
def log_deletion(self, **kwargs):
return
#@admin.register(Registro)
class RegistroAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','E','descripcion','Cargos','Depositos','Saldo')
change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def E(self, request, obj=None, **kwargs):
icon = '''
<svg width="16" height="16" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="right">
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
</g>
</defs>
<use xlink:href="#right" x="0" y="0" fill="#447e9b" />
</svg>
'''
#text = format_html('<img src="{}" alt="view">', icon)
if(request.debe > 0):
#return _boolean_icon(True)
return mark_safe('%s' % icon)
else:
return ""
E.allow_tags = True
@admin.register(Asiento)
class AsientoAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','descripcion','condomino','Cargos','Depositos','Saldo')
#change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
@admin.register(MovSinIdent)
class MovSinIdentAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'fecha_movimiento', 'descripcion', 'deposito')
date_hierarchy = 'fecha_movimiento'
save_on_top = True
inlines = [DetalleMovtoInline]
ordering = ('-fecha_movimiento',)
def get_queryset(self, request):
query = super(MovSinIdentAdmin, self).get_queryset(request)
filtered_query = query.filter(condomino__depto='0000').exclude(retiro__gt=0)
return filtered_query

5
condominio_aragon_37/apps.py Executable file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CondominioAragon37Config(AppConfig):
name = 'condominio_aragon_37'

177
condominio_aragon_37/models.py Executable file
View File

@@ -0,0 +1,177 @@
from django.db import models
from django.db.models import Q
from catalogos.models import Banco, CuentaContable
from django.utils.safestring import mark_safe
from django.templatetags.static import static
from django.utils.html import format_html
# Create your models here.
class CuentaBanco(models.Model):
banco = models.ForeignKey(Banco, on_delete=models.PROTECT, related_name='condominio_30')
clabe = models.CharField(max_length=18)
apoderado = models.CharField(max_length=60)
saldo_inicial = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_inicial = models.DateField(blank=True, null=True)
saldo_final = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_final = models.DateField(blank=True, null=True)
def __str__(self):
return '%s %s %d' % (self.clabe, self.apoderado[:10], self.saldo_final)
class Meta:
managed = True
db_table = 'condominio_aragon37_cuenta_banco'
verbose_name_plural = "Cuentas bancarias"
class Condomino(models.Model):
depto = models.CharField(max_length=15, blank=True, null=True)
propietario = models.CharField(max_length=60, blank=True, null=True)
poseedor = models.CharField(max_length=60, blank=True, null=True)
ubicacion = models.CharField(max_length=20, blank=True, null=True)
email = models.CharField(max_length=25, blank=True, null=True)
telefono = models.CharField(max_length=30, blank=True, null=True)
fecha_escrituracion = models.DateField(blank=True, null=True)
referencia = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
indiviso = models.DecimalField(max_digits=10, decimal_places=4, blank=True, null=True)
adeudo_inicial = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
fecha_adeudo_inicial = models.DateField(blank=True, null=True)
cargos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
abonos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return '%s %s' % (self.depto, self.poseedor)
def estado_cuenta(self):
icon_url = static('admin/img/icon-viewlink.svg')
text = format_html('<img src="{}" alt="view">', icon_url)
return mark_safe(
'<a href="/api-rest/estadocuentasadi10/%d">%s</a>' % (
self.id, text))
class Meta:
managed = True
db_table = 'condominio_aragon37_condomino'
ordering = ['depto']
class Movimiento(models.Model):
cuenta_banco = models.ForeignKey(CuentaBanco, default=1, on_delete=models.PROTECT, related_name='condominio_31')
fecha_movimiento = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
deposito = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
retiro = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
condomino = models.ForeignKey(Condomino, on_delete=models.PROTECT, related_name='condominio_32')
def __str__(self):
return u'%d %s %d %s' % (
self.id, self.fecha_movimiento.strftime('%d/%m/%Y'), self.deposito, self.descripcion[:15])
class Meta:
managed = True
db_table = 'condominio_aragon37_movimiento'
ordering = ['fecha_movimiento']
class DetalleMovimiento(models.Model):
movimiento = models.ForeignKey(Movimiento, verbose_name=('Movto'), on_delete=models.CASCADE, related_name='condominio_33')
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable Ingreso/Egreso'),
on_delete=models.CASCADE, related_name='condominio_34',
limit_choices_to=Q(clave_mayor='41') | Q(clave_mayor='51') | Q(
num_cuenta='2318'))
comentario = models.CharField(max_length=20, blank=True, null=True, default=".")
def __str__(self):
return '%s %d' % (self.cuenta_contable, self.monto)
class Meta:
managed = True
db_table = 'condominio_aragon37_detalle_movimiento'
ordering = ['movimiento']
class Registro(models.Model):
condomino = models.ForeignKey(Condomino, default=1, on_delete=models.PROTECT, related_name='condominio_35')
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='condominio_36',
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_aragon37_registro'
ordering = ['fecha']
verbose_name_plural = "Registros"
class Asiento(models.Model):
condomino = models.ForeignKey(Condomino, default=1, on_delete=models.PROTECT, related_name='condominio_92')
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='condominio_93',
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_aragon37_asiento'
ordering = ['fecha']
verbose_name_plural = "Auxiliar"
class CuotasCondominio(models.Model):
descripcion = models.CharField(max_length=30, blank=True, null=True)
mes_inicial = models.DateField(blank=True, null=True)
mes_final = models.DateField(blank=True, null=True)
dia_vencimiento = models.DecimalField(max_digits=2, decimal_places=0, blank=True, null=True, default=1)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='condominio_37')
condomino = models.ManyToManyField(Condomino, related_name='condominio_38')
def __str__(self):
return u'%s %s %s %d %s' % (
self.descripcion, self.mes_inicial.strftime('%m-%Y'), self.mes_final.strftime('%m-%Y'), self.monto,
self.cuenta_contable)
class Meta:
managed = True
db_table = 'condominio_aragon37_cuotas'
ordering = ['mes_inicial']
verbose_name_plural = "Cuotas"
class AcumuladoMes(models.Model):
cuenta_banco = models.CharField(max_length=20, blank=True, null=True)
mes = models.CharField(max_length=7, blank=True, null=True)
fecha_inicial = models.DateField(blank=True, null=True)
fecha_final = models.DateField(blank=True, null=True)
depositos = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
retiros = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return u'%s %s %s %s %d %d %d' % (
self.cuenta_banco, self.mes, self.fecha_inicial.strftime('%d/%m/%Y'), self.fecha_final.strftime('%d/%m/%Y'),
self.depositos, self.retiros, self.saldo)
class Meta:
managed = True
db_table = 'condominio_aragon37_acumulado_mes'
verbose_name_plural = "Depositos y retiros por mes"
class MovSinIdent(Movimiento):
class Meta:
proxy = True
verbose_name = 'Deposito sin identificar'
verbose_name_plural = 'Depositos sin identificar'

383
condominio_aragon_37/procesos.py Executable file
View File

@@ -0,0 +1,383 @@
from django.db import transaction
from django.db import connection
from .models import AcumuladoMes, Registro, CuotasCondominio, Movimiento, Condomino, CuentaBanco, Asiento
from catalogos.models import CuentaContable, PeriodoCorte
from ciec.procesos import dictfetchall, execsql
from datetime import datetime, timedelta
import pandas as pd
def run_estado_cuenta(condominos, filename):
consulta = '''
select r.id, c.depto, c.poseedor, r.fecha as FECHA, r.descripcion as DESCRIPCION,
r.haber as CARGOS, r.debe as DEPOSITOS, r.saldo as SALDO
from condominio_aragon37_registro r,
condominio_aragon37_condomino c
where r.condomino_id = c.id
and c.id = {id}
order by r.fecha desc, r.id desc
'''
writer = pd.ExcelWriter(filename,
engine='xlsxwriter',
datetime_format='dd/mmm/yyyy',
date_format='dd/mmm/yyyy')
for c in condominos:
q = consulta.format(id = c['id'])
rows = execsql(q)
df = pd.DataFrame(rows)
df['cargos'] = df['cargos'].astype(float)
df['depositos'] = df['depositos'].astype(float)
df['saldo'] = df['saldo'].astype(float)
df = df.drop(columns = ['id', 'depto', 'poseedor'])
df = df.rename(columns = {'fecha' : 'Fecha',
'descripcion' : 'Descripcion',
'cargos' : 'Cargos',
'depositos' : 'Depositos',
'saldo' : 'Saldo'
})
hoja = c['depto']
dfR = df.rename_axis(None)
i = len(dfR.index) + 10
j = len(dfR.index) + 7
dfR.to_excel(writer, sheet_name = hoja, startrow = 5)
titulo = " CONDOMINIO ARAGON 37 "
subtitulo = " ESTADO DE CUENTA DEL DEPARTAMENTO {depto} {poseedor} ".format(depto = hoja,
poseedor = c['poseedor'])
subtitulob = " SALDO AL {} POR $ {:,}".format('CORTE', c['adeudo'])
workbook = writer.book
worksheet = writer.sheets[hoja]
#formatos = styles_workbook(workbook)
f_titulos = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter'})
f_celdas = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
f_bordes = workbook.add_format({'bottom': 1})
f_descripcion = workbook.add_format({'align': 'left', 'valign': 'vjustify'})
f_numeros = workbook.add_format({'num_format': '#,##0.00', 'valign': 'vcenter'})
f_fechas = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'dd/mmm/yyyy' })
f_cabeceras = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top', 'align' : 'center', 'fg_color': '#D7E4BC', 'border': 1})
f_condicion1 = workbook.add_format({'bold': True, 'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
f_condicion2 = workbook.add_format({'bold': True, 'bg_color': '#C6EFCE', 'font_color': '#006100'})
f_ocultar = workbook.add_format({'font_color': '#FFFFFF'})
worksheet.set_column('B:B', 15, f_fechas)
worksheet.set_column('D:F', 15, f_numeros)
worksheet.set_column('C:C', 50, f_descripcion)
worksheet.merge_range('B2:F2', titulo, f_titulos)
worksheet.merge_range('B3:F3', subtitulo, f_titulos)
worksheet.merge_range('B4:F4', subtitulob, f_titulos)
worksheet.conditional_format('D7:D' + str(i),
{'type' : 'cell',
'criteria' : '=',
'value' : 0,
'format' : f_ocultar
})
worksheet.conditional_format('E7:E' + str(i),
{'type' : 'cell',
'criteria' : '=',
'value' : 0,
'format' : f_ocultar
})
worksheet.conditional_format('B7:C' + str(i),
{'type' : 'formula',
'criteria' : '=$E7>0',
'format' : f_condicion2
})
worksheet.conditional_format('B4:B4',
{'type' : 'formula',
'criteria' : '=$F$7>0',
'format' : f_condicion1
})
worksheet.conditional_format('B4:B4',
{'type' : 'formula',
'criteria' : '=$F$7<=0',
'format' : f_condicion2
})
for col_num, value in enumerate(dfR.columns.values):
worksheet.write(5, col_num + 1, value, f_cabeceras)
worksheet.conditional_format('B7:N' + str(i),
{'type': 'cell',
'criteria': '<>',
'value': '""',
'format': f_bordes})
worksheet.set_portrait()
worksheet.set_paper(1)
worksheet.center_horizontally()
#worksheet.center_vertically()
worksheet.repeat_rows(0, 5)
worksheet.print_area('B7:G' + str(i))
worksheet.fit_to_pages(1, 0)
#worksheet.hide_gridlines(0)
worksheet.set_header('&LCIEC Cuotas, Ingresos y Egresos Condominales &Rciec.adcondominio.com')
worksheet.set_footer('&CPágina &P de &N &RImpreso el &D')
writer.close()
return filename.getvalue()
def run_detalle_ingresos_egresos(fecha_inicial, fecha_final, filename):
consulta = '''
select min(fecha_movimiento) as fecha_inicio,
max(fecha_movimiento) as fecha_fin,
count(cc.num_cuenta) as cuantos,
cc.num_cuenta as cuenta,
cc.descripcion as conepto,
comentario as subconcepto,
case when sum(m.deposito) > 0 then sum(d.monto) else 0 end as deposito,
case when sum(m.retiro) > 0 then sum(d.monto) else 0 end as retiro
from condominio_aragon37_detalle_movimiento d,
condominio_aragon37_movimiento m,
cuenta_contable cc
where d.movimiento_id = m.id
and d.cuenta_contable_id = cc.id
and m.fecha_movimiento >= '{ini}'
and m.fecha_movimiento <= '{fin}'
group by cc.descripcion, comentario, cc.num_cuenta order by 4,5,6
'''
consulta = consulta.format(ini = fecha_inicial.strftime('%Y-%m-%d'), fin = fecha_final.strftime('%Y-%m-%d'))
rows = execsql(consulta)
df = pd.DataFrame(rows)
df['deposito'] = df['deposito'].astype(float)
df['retiro'] = df['retiro'].astype(float)
df = df.drop(columns = ['cuenta'])
df = df.rename(columns = { 'fecha_inicio': 'Fecha inicio',
'fecha_fin' : 'Fecha final',
'cuantos' : 'Cantidad',
'concepto' : 'Concepto',
'subconcepto' : 'subConcepto',
'deposito' : 'Deposito',
'retiro' : 'Retiro'
})
writer = pd.ExcelWriter(filename, engine='xlsxwriter', datetime_format='dd/mm/yyyy', date_format='dd/mm/yyyy')
titulo = "CONDOMINIO ARAGON 37"
subtitulo = "DETALLE DE INGRESOS Y EGRESOS DESDE EL {} HASTA EL {}".format(fecha_inicial.strftime('%d/%m/%Y'), fecha_final.strftime('%d/%m/%Y'))
dfR = df.rename_axis(None)
dfR.to_excel(writer, sheet_name = 'HOJA', startrow = 5)
i = len(dfR.index) + 10
j = len(dfR.index) + 7
workbook = writer.book
worksheet = writer.sheets['HOJA']
#
f_titulos = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter'})
f_celdas = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
f_bordes = workbook.add_format({'bottom': 1})
f_descripcion = workbook.add_format({'align': 'left', 'valign': 'vjustify'})
f_numeros = workbook.add_format({'num_format': '#,##0.00', 'valign': 'vcenter'})
f_fechas = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'dd/mmm/yyyy' })
f_cabeceras = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top', 'align' : 'center', 'fg_color': '#D7E4BC', 'border': 1})
f_condicion1 = workbook.add_format({'bold': True, 'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
f_condicion2 = workbook.add_format({'bold': True, 'bg_color': '#C6EFCE', 'font_color': '#006100'})
f_ocultar = workbook.add_format({'font_color': '#FFFFFF'})
worksheet.set_column('B:C', 15, f_fechas )
worksheet.set_column('G:H', 15, f_numeros )
worksheet.set_column('E:E', 40)
worksheet.set_column('F:F', 20)
worksheet.set_column('D:D', 10, f_celdas)
worksheet.merge_range('B2:I2', titulo, f_titulos)
worksheet.merge_range('B3:I3', subtitulo, f_titulos)
worksheet.write('G' + str(j), '=SUM(G7:G{row})'.format(row=j-1))
worksheet.write('H' + str(j), '=SUM(H7:H{row})'.format(row=j-1))
for col_num, value in enumerate(dfR.columns.values):
worksheet.write(5, col_num + 1, value, f_cabeceras )
worksheet.conditional_format('B7:N' + str(i),
{'type': 'cell',
'criteria': '<>',
'value': '""',
'format': f_bordes})
worksheet.set_portrait()
worksheet.set_paper(1)
worksheet.center_horizontally()
#worksheet.center_vertically()
worksheet.repeat_rows(0, 5)
worksheet.print_area('B7:I' + str(i))
worksheet.fit_to_pages(1, 0)
#worksheet.hide_gridlines(0)
worksheet.set_header('&LCIEC Cuotas, Ingresos y Egresos Condominales &Rciec.adcondominio.com')
worksheet.set_footer('&CPágina &P de &N &RImpreso el &D')
writer.close()
return filename.getvalue()
def run_acum_aragon37(condominio, shortname):
print(" generando acumulados %s " % shortname)
with transaction.atomic():
borrado = ''
nq1 = ''
nq2 = ''
#
# Borra acumulados
if shortname == "ARAGON37":
borrado = 'delete from condominio_aragon37_acumulado_mes'
nq1 = '''
select nombre, clabe as cuenta, cb.saldo_inicial, min(fecha_movimiento) as fecha
from condominio_aragon37_movimiento m,
condominio_aragon37_cuenta_banco cb,
periodo_corte p,
condominio c
where cb.id = m.cuenta_banco_id
and m.fecha_movimiento >= p.fecha_inicial
and m.fecha_movimiento <= p.fecha_final
and c.nombre = 'ARAGON37'
and p.id = 5
group by 1,2,3
order by 4,2
'''
nq2 = '''
select 'Condominio' as nombre, clabe as cuenta, to_char(fecha_movimiento,'MM-YYYY') as mes,
min(fecha_movimiento) as fec_ini,
max(fecha_movimiento) as fec_fin,
round(sum(deposito),2) as depositos,
round(sum(retiro),2) as retiros,
round(sum(deposito)-sum(retiro),2) as diferencia
from condominio_aragon37_movimiento m,
condominio_aragon37_cuenta_banco cb,
periodo_corte p
where cb.id = m.cuenta_banco_id
and fecha_movimiento >= p.fecha_inicial
and fecha_movimiento <= p.fecha_final
and p.id = 5
group by 1,2,3
order by 2,4,3
'''
#print(borrado,nq1,nq2)
n = execsql(borrado)
#
# Trae saldo inicial de cada cuenta
saldo_condominio = 0
rows = execsql(nq1)
print(rows)
#
# Por cada cuenta
for r in rows:
saldo = float(r['saldo_inicial'])
#
# Agrega depositos y retiros por cuenta y mes
rows2 = execsql(nq2)
for r2 in rows2:
if r2['cuenta'] == r['cuenta']:
saldo = round(saldo + float(r2['depositos']) - float(r2['retiros']), 2)
print(r2['cuenta'], r2['mes'], r2['depositos'], r2['retiros'], saldo)
reg = AcumuladoMes(cuenta_banco=r2['cuenta'], \
mes=r2['mes'], \
fecha_inicial=r2['fec_ini'], \
fecha_final=r2['fec_fin'], \
depositos=r2['depositos'], \
retiros=r2['retiros'], \
saldo=saldo)
reg.save()
saldo_condominio = saldo_condominio + saldo
# print(saldo_condominio)
#
# Actualiza saldo en periodos
oPer = PeriodoCorte.objects.get(id=5)
oPer.saldo_final = saldo_condominio
oPer.save()
def run_determinacionSaldos_aragon37(condomino):
print(" determinando saldos %s " % condomino.depto)
with transaction.atomic():
# tipo = TipoMovimiento.objects.get(id=21)
# prop = TipoMovimiento.objects.get(id=30)
cuenta = CuentaContable.objects.get(id=82)
# prove = Proveedore.objects.get(id=1)
#
# Borra asientos
n = execsql('delete from condominio_aragon37_registro where condomino_id = %s' % condomino.id)
#
# Agrega adeudo inicial
if not condomino.depto == '0000':
ade = condomino.adeudo_inicial
sal = 0
deb = 0
sal = sal + deb - ade
# adeudo = condomino.adeudo_inicial
reg_i = Registro(fecha=condomino.fecha_adeudo_inicial, \
descripcion='SALDO INICIAL A LA FECHA', \
debe=deb, \
haber=ade, \
saldo=sal, \
cuenta_contable=cuenta, \
condomino=condomino)
reg_i.save()
#
# Agrega adeudos por cuotas
rows = CuotasCondominio.objects.all().order_by('mes_inicial')
for r in rows:
delta = (r.mes_final - r.mes_inicial)
# print(r.descripcion,r.mes_inicial,r.mes_final,r.monto,r.cuenta_contable,delta.days)
condom = r.condomino.filter(depto__contains=condomino.depto)
if condom:
base = r.mes_inicial
for x in range(0, delta.days + 1):
fecha = base + timedelta(days=x)
if fecha.day == 1:
reg_a = Registro(fecha=fecha, \
descripcion='CARGO {}'.format(r.descripcion), \
debe=0, \
haber=r.monto, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_a.save()
#
# Agrega depositos por movimiento de banco
if not condomino.depto == '0000':
movtos = Movimiento.objects.filter(condomino__id=condomino.id).order_by('fecha_movimiento', 'id')
for m in movtos:
if m.fecha_movimiento >= datetime(2025,1,1).date():
reg_m = Registro(fecha=m.fecha_movimiento, \
descripcion=m.descripcion, \
debe=m.deposito, \
haber=0, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_m.save()
asientos = Asiento.objects.filter(condomino_id=condomino.id).order_by('fecha', 'id')
for a in asientos:
reg_a = Registro(fecha=a.fecha, \
descripcion=a.descripcion, \
debe=a.debe, \
haber=a.haber, \
saldo=a.saldo, \
cuenta_contable=a.cuenta_contable, \
condomino=condomino)
reg_a.save()
# Recalcula saldos
if not condomino.depto == '0000':
sal = 0
car = 0
dep = 0
rec = Registro.objects.filter(condomino__id=condomino.id).order_by('fecha', 'id')
for rr in rec:
car = car + rr.haber
dep = dep + rr.debe
sal = sal + rr.haber - rr.debe
rr.saldo = sal
rr.save()
reg_c = Condomino.objects.get(id=condomino.id)
reg_c.cargos = car
reg_c.abonos = dep
reg_c.saldo = sal
reg_c.save()

View File

165
condominio_balcones/admin.py Executable file
View File

@@ -0,0 +1,165 @@
from django.contrib import admin
from .models import Movimiento, DetalleMovimiento, CuentaBanco, CuotasCondominio, Condomino, AcumuladoMes, Registro, MovSinIdent, Asiento
from .procesos import run_determinacionSaldos_balcones
from django.utils.safestring import mark_safe
# Register your models here.
class DetalleMovtoInline(admin.TabularInline):
model = DetalleMovimiento
fields = ['cuenta_contable', 'monto', 'comentario']
def get_extra(self, request, obj=None, **kwargs):
extra = 4
return extra
@admin.register(Movimiento)
class MovtoAdmin(admin.ModelAdmin):
list_display = ('id','fecha_movimiento','descripcion','retiros','depositos','condomino', 'conciliacion')
search_fields = ('descripcion',)
date_hierarchy = 'fecha_movimiento'
ordering = ('-fecha_movimiento',)
save_on_top = True
inlines = [DetalleMovtoInline]
def retiros(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiro)
def depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.deposito)
def conciliacion(self, request, obj=None, **kwargs):
cantidades = DetalleMovimiento.objects.filter(movimiento_id=request.id).values_list('monto', flat=True)
total = sum(cantidades)
if (total != (request.retiro + request.deposito)):
return False
else:
return True
conciliacion.boolean = True
@admin.register(CuentaBanco)
class CuentaBancoAdmin(admin.ModelAdmin):
list_display = ('banco','clabe','apoderado')
@admin.register(CuotasCondominio)
class CuotasAdmin(admin.ModelAdmin):
list_display = ('descripcion', 'mes_inicial', 'mes_final', 'cantidad','cuenta_contable')
ordering = ('-mes_inicial',)
def cantidad(self, request, obj=None, **kwargs):
return "{:,}".format(request.monto)
@admin.register(Condomino)
class CondominoAdmin(admin.ModelAdmin):
list_display = ('depto', 'poseedor', 'adeudo_inicio', 'cuotas', 'depositos', 'adeudo_actual')
search_fields = ('depto', 'propietario', 'poseedor')
actions = ['determina_saldos']
def adeudo_inicio(self, request, obj=None, **kwargs):
return "{:,}".format(request.adeudo_inicial)
def cuotas(self, request, obj=None, **kwargs):
cargos = request.cargos - request.adeudo_inicial
return "{:,}".format(cargos)
def depositos(self, request, obj=None, **kwargs):
pagos = request.abonos
return "{:,}".format(pagos)
def adeudo_actual(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def determina_saldos(self, request, queryset):
for obj in queryset:
# print(" determina saldos %s " % obj.depto)
run_determinacionSaldos_balcones(obj)
#pass
self.message_user(request, " Fin del proceso de determinacion de saldos ")
determina_saldos.short_description = "Determinacion de Saldos"
@admin.register(AcumuladoMes)
class AcumuladoAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'mes', 'fecha_inicial', 'fecha_final', 'Depositado', 'Retirado', 'Saldos')
ordering = ('-fecha_inicial', 'cuenta_banco',)
#actions = ['export_as_csv']
#change_list_template = "admin/titulo_acumulados.html"
def Depositado(self, request, obj=None, **kwargs):
return "{:,}".format(request.depositos)
def Retirado(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiros)
def Saldos(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
class dontLog:
def log_deletion(self, **kwargs):
return
@admin.register(Asiento)
class AsientoAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','descripcion','condomino','Cargos','Depositos','Saldo')
#change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
#@admin.register(Registro)
class RegistroAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','E','descripcion','Cargos','Depositos','Saldo')
change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def E(self, request, obj=None, **kwargs):
icon = '''
<svg width="16" height="16" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="right">
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
</g>
</defs>
<use xlink:href="#right" x="0" y="0" fill="#447e9b" />
</svg>
'''
#text = format_html('<img src="{}" alt="view">', icon)
if(request.debe > 0):
#return _boolean_icon(True)
return mark_safe('%s' % icon)
else:
return ""
E.allow_tags = True
@admin.register(MovSinIdent)
class MovSinIdentAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'fecha_movimiento', 'descripcion', 'deposito')
date_hierarchy = 'fecha_movimiento'
save_on_top = True
inlines = [DetalleMovtoInline]
ordering = ('-fecha_movimiento',)
def get_queryset(self, request):
query = super(MovSinIdentAdmin, self).get_queryset(request)
filtered_query = query.filter(condomino__depto='0000').exclude(retiro__gt=0)
return filtered_query

5
condominio_balcones/apps.py Executable file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CondominioBalconesConfig(AppConfig):
name = 'condominio_balcones'

179
condominio_balcones/models.py Executable file
View File

@@ -0,0 +1,179 @@
from django.db import models
from django.db.models import Q
from catalogos.models import Banco, CuentaContable
from django.utils.safestring import mark_safe
from django.templatetags.static import static
from django.utils.html import format_html
# Create your models here.
class CuentaBanco(models.Model):
banco = models.ForeignKey(Banco, related_name='condo_130', on_delete=models.PROTECT)
clabe = models.CharField(max_length=18)
apoderado = models.CharField(max_length=60)
saldo_inicial = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_inicial = models.DateField(blank=True, null=True)
saldo_final = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_final = models.DateField(blank=True, null=True)
def __str__(self):
return '%s %s %d' % (self.clabe, self.apoderado[:10], self.saldo_final)
class Meta:
managed = True
db_table = 'condominio_balcones_cuenta_banco'
verbose_name_plural = "Cuentas bancarias"
class Condomino(models.Model):
depto = models.CharField(max_length=15, blank=True, null=True)
propietario = models.CharField(max_length=60, blank=True, null=True)
poseedor = models.CharField(max_length=60, blank=True, null=True)
ubicacion = models.CharField(max_length=20, blank=True, null=True)
email = models.CharField(max_length=25, blank=True, null=True)
telefono = models.CharField(max_length=30, blank=True, null=True)
fecha_escrituracion = models.DateField(blank=True, null=True)
referencia = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
indiviso = models.DecimalField(max_digits=10, decimal_places=4, blank=True, null=True)
adeudo_inicial = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
fecha_adeudo_inicial = models.DateField(blank=True, null=True)
cargos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
abonos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return '%s %s' % (self.depto, self.poseedor)
def estado_cuenta(self):
icon_url = static('admin/img/icon-viewlink.svg')
text = format_html('<img src="{}" alt="view">', icon_url)
return mark_safe(
'<a href="/api-rest/estadocuentabalcones/%d">%s</a>' % (
self.id, text))
class Meta:
managed = True
db_table = 'condominio_balcones_condomino'
ordering = ['depto']
class Movimiento(models.Model):
cuenta_banco = models.ForeignKey(CuentaBanco, default=1,related_name='condo_131', on_delete=models.PROTECT)
fecha_movimiento = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
deposito = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
retiro = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
condomino = models.ForeignKey(Condomino, related_name='condo_139', on_delete=models.PROTECT)
def __str__(self):
return u'%d %s %d %s' % (
self.id, self.fecha_movimiento.strftime('%d/%m/%Y'), self.deposito, self.descripcion[:15])
class Meta:
managed = True
db_table = 'condominio_balcones_movimiento'
ordering = ['fecha_movimiento']
class DetalleMovimiento(models.Model):
movimiento = models.ForeignKey(Movimiento, verbose_name=('Movto'), related_name='condo_132', on_delete=models.CASCADE)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable Ingreso/Egreso'),
related_name='condo_133',
on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='41') | Q(clave_mayor='51') | Q(
num_cuenta='2318'))
comentario = models.CharField(max_length=20, blank=True, null=True, default=".")
def __str__(self):
return '%s %d' % (self.cuenta_contable, self.monto)
class Meta:
managed = True
db_table = 'condominio_balcones_detalle_movimiento'
ordering = ['movimiento']
class Registro(models.Model):
condomino = models.ForeignKey(Condomino, default=1, related_name='condo_134', on_delete=models.PROTECT)
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='condo_135', on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_balcones_registro'
ordering = ['fecha']
verbose_name_plural = "Registros"
class Asiento(models.Model):
condomino = models.ForeignKey(Condomino, default=1, on_delete=models.PROTECT, related_name='condo_140')
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='condo_136',
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_balcones_asiento'
ordering = ['fecha']
verbose_name_plural = "Auxiliar"
class CuotasCondominio(models.Model):
descripcion = models.CharField(max_length=30, blank=True, null=True)
mes_inicial = models.DateField(blank=True, null=True)
mes_final = models.DateField(blank=True, null=True)
dia_vencimiento = models.DecimalField(max_digits=2, decimal_places=0, blank=True, null=True, default=1)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='condo_137', on_delete=models.CASCADE)
condomino = models.ManyToManyField(Condomino, related_name='condo_138')
def __str__(self):
return u'%s %s %s %d %s' % (
self.descripcion, self.mes_inicial.strftime('%m-%Y'), self.mes_final.strftime('%m-%Y'), self.monto,
self.cuenta_contable)
class Meta:
managed = True
db_table = 'condominio_balcones_cuotas'
ordering = ['mes_inicial']
verbose_name_plural = "Cuotas"
class AcumuladoMes(models.Model):
cuenta_banco = models.CharField(max_length=20, blank=True, null=True)
mes = models.CharField(max_length=7, blank=True, null=True)
fecha_inicial = models.DateField(blank=True, null=True)
fecha_final = models.DateField(blank=True, null=True)
depositos = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
retiros = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return u'%s %s %s %s %d %d %d' % (
self.cuenta_banco, self.mes, self.fecha_inicial.strftime('%d/%m/%Y'), self.fecha_final.strftime('%d/%m/%Y'),
self.depositos, self.retiros, self.saldo)
class Meta:
managed = True
db_table = 'condominio_balcones_acumulado_mes'
verbose_name_plural = "Depositos y retiros por mes"
class MovSinIdent(Movimiento):
class Meta:
proxy = True
verbose_name = 'Deposito sin identificar'
verbose_name_plural = 'Depositos sin identificar'

179
condominio_balcones/procesos.py Executable file
View File

@@ -0,0 +1,179 @@
from django.db import transaction
from django.db import connection
from .models import AcumuladoMes, Registro, CuotasCondominio, Movimiento, Condomino, CuentaBanco, Asiento
from catalogos.models import CuentaContable, PeriodoCorte
from ciec.procesos import dictfetchall, execsql
from datetime import datetime, timedelta
def run_acum_balcones(condominio, shortname):
print(" generando acumulados %s " % shortname)
with transaction.atomic():
borrado = ''
nq1 = ''
nq2 = ''
#
# Borra acumulados
if shortname == "BALCONES":
borrado = 'delete from condominio_balcones_acumulado_mes'
nq1 = '''
select nombre, clabe as cuenta, cb.saldo_inicial, min(fecha_movimiento) as fecha
from condominio_balcones_movimiento m,
condominio_balcones_cuenta_banco cb,
periodo_corte p,
condominio c
where cb.id = m.cuenta_banco_id
and m.fecha_movimiento >= p.fecha_inicial
and m.fecha_movimiento <= p.fecha_final
and c.nombre = 'BALCONES'
and p.id = 8
group by 1,2,3
order by 4,2
'''
nq2 = '''
select 'Condominio' as nombre, clabe as cuenta, to_char(fecha_movimiento,'MM-YYYY') as mes,
min(fecha_movimiento) as fec_ini,
max(fecha_movimiento) as fec_fin,
round(sum(deposito),2) as depositos,
round(sum(retiro),2) as retiros,
round(sum(deposito)-sum(retiro),2) as diferencia
from condominio_balcones_movimiento m,
condominio_balcones_cuenta_banco cb,
periodo_corte p
where cb.id = m.cuenta_banco_id
and fecha_movimiento >= p.fecha_inicial
and fecha_movimiento <= p.fecha_final
and p.id = 8
group by 1,2,3
order by 2,4,3
'''
#print(borrado,nq1,nq2)
n = execsql(borrado)
#
# Trae saldo inicial de cada cuenta
saldo_condominio = 0
rows = execsql(nq1)
print(rows)
#
# Por cada cuenta
for r in rows:
saldo = float(r['saldo_inicial'])
#
# Agrega depositos y retiros por cuenta y mes
rows2 = execsql(nq2)
for r2 in rows2:
if r2['cuenta'] == r['cuenta']:
saldo = round(saldo + float(r2['depositos']) - float(r2['retiros']), 2)
#print(r2['cuenta'], r2['mes'], r2['fec_ini'], r2['fec_fin'], r2['depositos'], r2['retiros'], saldo)
reg = AcumuladoMes(cuenta_banco=r2['cuenta'], \
mes=r2['mes'], \
fecha_inicial=r2['fec_ini'], \
fecha_final=r2['fec_fin'], \
depositos=r2['depositos'], \
retiros=r2['retiros'], \
saldo=saldo)
print(' previo salva registro ')
reg.save()
if r['cuenta'] != '000000000000000000':
saldo_condominio = saldo_condominio + saldo
#print('actualiza saldo con ', saldo_condominio)
#
# Actualiza saldo en periodos
oPer = PeriodoCorte.objects.get(id=8)
oPer.saldo_final = saldo_condominio
oPer.save()
def run_determinacionSaldos_balcones(condomino):
print(" determinando saldos %s " % condomino.depto)
with transaction.atomic():
# tipo = TipoMovimiento.objects.get(id=21)
# prop = TipoMovimiento.objects.get(id=30)
cuenta = CuentaContable.objects.get(id=82)
# prove = Proveedore.objects.get(id=1)
#
# Borra asientos
n = execsql('delete from condominio_balcones_registro where condomino_id = %s' % condomino.id)
#
# Agrega adeudo inicial
if not condomino.depto == '0000':
ade = condomino.adeudo_inicial
sal = 0
deb = 0
sal = sal + deb - ade
# adeudo = condomino.adeudo_inicial
reg_i = Registro(fecha=condomino.fecha_adeudo_inicial, \
descripcion='SALDO INICIAL A LA FECHA', \
debe=deb, \
haber=ade, \
saldo=sal, \
cuenta_contable=cuenta, \
condomino=condomino)
reg_i.save()
#
# Agrega adeudos por cuotas
rows = CuotasCondominio.objects.all().order_by('mes_inicial')
for r in rows:
delta = (r.mes_final - r.mes_inicial)
# print(r.descripcion,r.mes_inicial,r.mes_final,r.monto,r.cuenta_contable,delta.days)
condom = r.condomino.filter(depto__contains=condomino.depto)
if condom:
base = r.mes_inicial
for x in range(0, delta.days + 1):
fecha = base + timedelta(days=x)
if fecha.day == 1:
reg_a = Registro(fecha=fecha, \
descripcion='CARGO {}'.format(r.descripcion), \
debe=0, \
haber=r.monto, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_a.save()
#
# Agrega depositos por movimiento de banco
if not condomino.depto == '0000':
movtos = Movimiento.objects.filter(condomino__id=condomino.id).order_by('fecha_movimiento', 'id')
for m in movtos:
reg_m = Registro(fecha=m.fecha_movimiento, \
descripcion=m.descripcion, \
debe=m.deposito, \
haber=0, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_m.save()
asientos = Asiento.objects.filter(condomino_id=condomino.id).order_by('fecha', 'id')
for a in asientos:
reg_a = Registro(fecha=a.fecha, \
descripcion=a.descripcion, \
debe=a.debe, \
haber=a.haber, \
saldo=a.saldo, \
cuenta_contable=a.cuenta_contable, \
condomino=condomino)
reg_a.save()
# Recalcula saldos
if not condomino.depto == '0000':
sal = 0
car = 0
dep = 0
rec = Registro.objects.filter(condomino__id=condomino.id).order_by('fecha', 'id')
for rr in rec:
car = car + rr.haber
dep = dep + rr.debe
sal = sal + rr.haber - rr.debe
rr.saldo = sal
rr.save()
reg_c = Condomino.objects.get(id=condomino.id)
reg_c.cargos = car
reg_c.abonos = dep
reg_c.saldo = sal
reg_c.save()

3
condominio_balcones/tests.py Executable file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

0
condominio_balcones/views.py Executable file
View File

View File

View File

@@ -0,0 +1,205 @@
from django.contrib import admin
from .models import Movimiento, DetalleMovimiento, CuentaBanco, CuotasCondominio, Condomino, AcumuladoMes, Registro, MovSinIdent, Asiento
from .procesos import run_determinacionSaldos_coyoacan, run_detalle_ingresos_egresos, run_estado_cuenta
from django.utils.safestring import mark_safe
from io import BytesIO
from django.http import HttpResponse
# Register your models here.
class DetalleMovtoInline(admin.TabularInline):
model = DetalleMovimiento
fields = ['cuenta_contable', 'monto', 'comentario']
def get_extra(self, request, obj=None, **kwargs):
extra = 4
return extra
@admin.register(Movimiento)
class MovtoAdmin(admin.ModelAdmin):
list_display = ('id','fecha_movimiento','descripcion','retiros','depositos','condomino', 'conciliacion')
search_fields = ('descripcion',)
date_hierarchy = 'fecha_movimiento'
ordering = ('-fecha_movimiento',)
save_on_top = True
inlines = [DetalleMovtoInline]
def retiros(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiro)
def depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.deposito)
def conciliacion(self, request, obj=None, **kwargs):
cantidades = DetalleMovimiento.objects.filter(movimiento_id=request.id).values_list('monto', flat=True)
total = sum(cantidades)
if (total != (request.retiro + request.deposito)):
return False
else:
return True
conciliacion.boolean = True
@admin.register(CuentaBanco)
class CuentaBancoAdmin(admin.ModelAdmin):
list_display = ('banco','clabe','apoderado')
@admin.register(CuotasCondominio)
class CuotasAdmin(admin.ModelAdmin):
list_display = ('descripcion', 'mes_inicial', 'mes_final', 'cantidad','cuenta_contable')
ordering = ('-mes_inicial',)
def cantidad(self, request, obj=None, **kwargs):
return "{:,}".format(request.monto)
@admin.register(Condomino)
class CondominoAdmin(admin.ModelAdmin):
list_display = ('depto', 'poseedor', 'adeudo_inicio', 'cuotas', 'depositos', 'adeudo_actual')
search_fields = ('depto', 'propietario', 'poseedor')
actions = ['determina_saldos', 'reporte_individual']
def adeudo_inicio(self, request, obj=None, **kwargs):
return "{:,}".format(request.adeudo_inicial)
def cuotas(self, request, obj=None, **kwargs):
cargos = request.cargos - request.adeudo_inicial
return "{:,}".format(cargos)
def depositos(self, request, obj=None, **kwargs):
pagos = request.abonos
return "{:,}".format(pagos)
def adeudo_actual(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def determina_saldos(self, request, queryset):
for obj in queryset:
# print(" determina saldos %s " % obj.depto)
run_determinacionSaldos_coyoacan(obj)
#pass
self.message_user(request, " Fin del proceso de determinacion de saldos ")
def reporte_individual(self, request, queryset):
condominos = []
for obj in queryset:
item = {}
item['id'] = obj.id
item['depto'] = obj.depto
item['poseedor'] = obj.poseedor
item['adeudo'] = obj.saldo
condominos.append(item)
#print(condominos)
filename = 'ciec_output_ec.xlsx'
stream = BytesIO()
data = run_estado_cuenta(condominos, stream)
self.message_user(request, "Fin del proceso, verifique area de descargas ")
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
response.write(data)
return response
reporte_individual.short_description = "Descarga estado de cuenta"
determina_saldos.short_description = "Determinacion de Saldos"
@admin.register(AcumuladoMes)
class AcumuladoAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'mes', 'fecha_inicial', 'fecha_final', 'Depositado', 'Retirado', 'Saldos')
ordering = ('-fecha_inicial', 'cuenta_banco',)
actions = ['detalle_ing_egr']
#change_list_template = "admin/titulo_acumulados.html"
def Depositado(self, request, obj=None, **kwargs):
return "{:,}".format(request.depositos)
def Retirado(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiros)
def Saldos(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def detalle_ing_egr(self, request, queryset):
dates = []
for obj in queryset:
dates.append(obj.fecha_inicial)
dates.append(obj.fecha_final)
filename = 'ciec_output_ie.xlsx'
stream = BytesIO()
data = run_detalle_ingresos_egresos(min(dates), max(dates), stream)
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
response.write(data)
return(response)
detalle_ing_egr.short_description = "Descargar detalle de ingresos y egresos"
#Detalle.allow_tags = True
class dontLog:
def log_deletion(self, **kwargs):
return
@admin.register(Asiento)
class AsientoAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','descripcion','condomino','Cargos','Depositos','Saldo')
#change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
#@admin.register(Registro)
class RegistroAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','E','descripcion','Cargos','Depositos','Saldo')
change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def E(self, request, obj=None, **kwargs):
icon = '''
<svg width="16" height="16" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="right">
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
</g>
</defs>
<use xlink:href="#right" x="0" y="0" fill="#447e9b" />
</svg>
'''
#text = format_html('<img src="{}" alt="view">', icon)
if(request.debe > 0):
#return _boolean_icon(True)
return mark_safe('%s' % icon)
else:
return ""
E.allow_tags = True
@admin.register(MovSinIdent)
class MovSinIdentAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'fecha_movimiento', 'descripcion', 'deposito')
date_hierarchy = 'fecha_movimiento'
save_on_top = True
inlines = [DetalleMovtoInline]
ordering = ('-fecha_movimiento',)
def get_queryset(self, request):
query = super(MovSinIdentAdmin, self).get_queryset(request)
filtered_query = query.filter(condomino__depto='0000').exclude(retiro__gt=0)
return filtered_query

View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CondominioMatiasRomeroConfig(AppConfig):
name = 'condominio_coyoacan'

View File

@@ -0,0 +1,179 @@
from django.db import models
from django.db.models import Q
from catalogos.models import Banco, CuentaContable
from django.utils.safestring import mark_safe
from django.templatetags.static import static
from django.utils.html import format_html
# Create your models here.
class CuentaBanco(models.Model):
banco = models.ForeignKey(Banco, related_name='micondo_421', on_delete=models.PROTECT)
clabe = models.CharField(max_length=18)
apoderado = models.CharField(max_length=60)
saldo_inicial = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_inicial = models.DateField(blank=True, null=True)
saldo_final = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_final = models.DateField(blank=True, null=True)
def __str__(self):
return '%s %s %d' % (self.clabe, self.apoderado[:10], self.saldo_final)
class Meta:
managed = True
db_table = 'condominio_coyoacan_cuenta_banco'
verbose_name_plural = "Cuentas bancarias"
class Condomino(models.Model):
depto = models.CharField(max_length=15, blank=True, null=True)
propietario = models.CharField(max_length=60, blank=True, null=True)
poseedor = models.CharField(max_length=60, blank=True, null=True)
ubicacion = models.CharField(max_length=20, blank=True, null=True)
email = models.CharField(max_length=25, blank=True, null=True)
telefono = models.CharField(max_length=30, blank=True, null=True)
fecha_escrituracion = models.DateField(blank=True, null=True)
referencia = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
indiviso = models.DecimalField(max_digits=10, decimal_places=4, blank=True, null=True)
adeudo_inicial = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
fecha_adeudo_inicial = models.DateField(blank=True, null=True)
cargos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
abonos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return '%s %s' % (self.depto, self.poseedor)
def estado_cuenta(self):
icon_url = static('admin/img/icon-viewlink.svg')
text = format_html('<img src="{}" alt="view">', icon_url)
return mark_safe(
'<a href="/api-rest/estadocuentacoyoacan/%d">%s</a>' % (
self.id, text))
class Meta:
managed = True
db_table = 'condominio_coyoacan_condomino'
ordering = ['depto']
class Movimiento(models.Model):
cuenta_banco = models.ForeignKey(CuentaBanco, default=1,related_name='micondo_422', on_delete=models.PROTECT)
fecha_movimiento = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
deposito = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
retiro = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
condomino = models.ForeignKey(Condomino, related_name='micondo_423', on_delete=models.PROTECT)
def __str__(self):
return u'%d %s %d %s' % (
self.id, self.fecha_movimiento.strftime('%d/%m/%Y'), self.deposito, self.descripcion[:15])
class Meta:
managed = True
db_table = 'condominio_coyoacan_movimiento'
ordering = ['fecha_movimiento']
class DetalleMovimiento(models.Model):
movimiento = models.ForeignKey(Movimiento, verbose_name=('Movto'), related_name='micondo_424', on_delete=models.CASCADE)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable Ingreso/Egreso'),
related_name='micondo_425',
on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='41') | Q(clave_mayor='51') | Q(
num_cuenta='2318'))
comentario = models.CharField(max_length=20, blank=True, null=True, default=".")
def __str__(self):
return '%s %d' % (self.cuenta_contable, self.monto)
class Meta:
managed = True
db_table = 'condominio_coyoacan_detalle_movimiento'
ordering = ['movimiento']
class Registro(models.Model):
condomino = models.ForeignKey(Condomino, default=1, related_name='micondo_426', on_delete=models.PROTECT)
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='micondo_427', on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_coyoacan_registro'
ordering = ['fecha']
verbose_name_plural = "Registros"
class Asiento(models.Model):
condomino = models.ForeignKey(Condomino, default=1, on_delete=models.PROTECT, related_name='micondo_496')
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='micondo_497',
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_coyoacan_asiento'
ordering = ['fecha']
verbose_name_plural = "Auxiliar"
class CuotasCondominio(models.Model):
descripcion = models.CharField(max_length=30, blank=True, null=True)
mes_inicial = models.DateField(blank=True, null=True)
mes_final = models.DateField(blank=True, null=True)
dia_vencimiento = models.DecimalField(max_digits=2, decimal_places=0, blank=True, null=True, default=1)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='micondo_428', on_delete=models.CASCADE)
condomino = models.ManyToManyField(Condomino, related_name='micondo_429')
def __str__(self):
return u'%s %s %s %d %s' % (
self.descripcion, self.mes_inicial.strftime('%m-%Y'), self.mes_final.strftime('%m-%Y'), self.monto,
self.cuenta_contable)
class Meta:
managed = True
db_table = 'condominio_coyoacan_cuotas'
ordering = ['mes_inicial']
verbose_name_plural = "Cuotas"
class AcumuladoMes(models.Model):
cuenta_banco = models.CharField(max_length=20, blank=True, null=True)
mes = models.CharField(max_length=7, blank=True, null=True)
fecha_inicial = models.DateField(blank=True, null=True)
fecha_final = models.DateField(blank=True, null=True)
depositos = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
retiros = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return u'%s %s %s %s %d %d %d' % (
self.cuenta_banco, self.mes, self.fecha_inicial.strftime('%d/%m/%Y'), self.fecha_final.strftime('%d/%m/%Y'),
self.depositos, self.retiros, self.saldo)
class Meta:
managed = True
db_table = 'condominio_coyoacan_acumulado_mes'
verbose_name_plural = "Depositos y retiros por mes"
class MovSinIdent(Movimiento):
class Meta:
proxy = True
verbose_name = 'Deposito sin identificar'
verbose_name_plural = 'Depositos sin identificar'

View File

@@ -0,0 +1,382 @@
from django.db import transaction
from django.db import connection
from .models import AcumuladoMes, Registro, CuotasCondominio, Movimiento, Condomino, CuentaBanco, Asiento
from catalogos.models import CuentaContable, PeriodoCorte
from ciec.procesos import dictfetchall, execsql, styles_workbook
from datetime import datetime, timedelta
import pandas as pd
def run_estado_cuenta(condominos, filename):
consulta = '''
select r.id, c.depto, c.poseedor, r.fecha as FECHA, r.descripcion as DESCRIPCION,
r.haber as CARGOS, r.debe as DEPOSITOS, r.saldo as SALDO
from condominio_coyoacan_registro r,
condominio_coyoacan_condomino c
where r.condomino_id = c.id
and c.id = {id}
order by r.fecha desc, r.id desc
'''
writer = pd.ExcelWriter(filename,
engine='xlsxwriter',
datetime_format='dd/mmm/yyyy',
date_format='dd/mmm/yyyy')
for c in condominos:
q = consulta.format(id = c['id'])
rows = execsql(q)
df = pd.DataFrame(rows)
df['cargos'] = df['cargos'].astype(float)
df['depositos'] = df['depositos'].astype(float)
df['saldo'] = df['saldo'].astype(float)
df = df.drop(columns = ['id', 'depto', 'poseedor'])
df = df.rename(columns = {'fecha' : 'Fecha',
'descripcion' : 'Descripcion',
'cargos' : 'Cargos',
'depositos' : 'Depositos',
'saldo' : 'Saldo'
})
hoja = c['depto']
dfR = df.rename_axis(None)
i = len(dfR.index) + 10
j = len(dfR.index) + 7
dfR.to_excel(writer, sheet_name = hoja, startrow = 5)
titulo = " CONDOMINIO COYOACAN 1045 "
subtitulo = " ESTADO DE CUENTA DEL DEPARTAMENTO {depto} {poseedor} ".format(depto = hoja,
poseedor = c['poseedor'])
subtitulob = " SALDO AL {} POR $ {:,}".format('CORTE', c['adeudo'])
workbook = writer.book
worksheet = writer.sheets[hoja]
#formatos = styles_workbook(workbook)
f_titulos = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter'})
f_celdas = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
f_bordes = workbook.add_format({'bottom': 1})
f_descripcion = workbook.add_format({'align': 'left', 'valign': 'vjustify'})
f_numeros = workbook.add_format({'num_format': '#,##0.00', 'valign': 'vcenter'})
f_fechas = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'dd/mmm/yyyy' })
f_cabeceras = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top', 'align' : 'center', 'fg_color': '#D7E4BC', 'border': 1})
f_condicion1 = workbook.add_format({'bold': True, 'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
f_condicion2 = workbook.add_format({'bold': True, 'bg_color': '#C6EFCE', 'font_color': '#006100'})
f_ocultar = workbook.add_format({'font_color': '#FFFFFF'})
worksheet.set_column('B:B', 15, f_fechas)
worksheet.set_column('D:F', 15, f_numeros)
worksheet.set_column('C:C', 50, f_descripcion)
worksheet.merge_range('B2:F2', titulo, f_titulos)
worksheet.merge_range('B3:F3', subtitulo, f_titulos)
worksheet.merge_range('B4:F4', subtitulob, f_titulos)
worksheet.conditional_format('D7:D' + str(i),
{'type' : 'cell',
'criteria' : '=',
'value' : 0,
'format' : f_ocultar
})
worksheet.conditional_format('E7:E' + str(i),
{'type' : 'cell',
'criteria' : '=',
'value' : 0,
'format' : f_ocultar
})
worksheet.conditional_format('B7:C' + str(i),
{'type' : 'formula',
'criteria' : '=$E7>0',
'format' : f_condicion2
})
worksheet.conditional_format('B4:B4',
{'type' : 'formula',
'criteria' : '=$F$7>0',
'format' : f_condicion1
})
worksheet.conditional_format('B4:B4',
{'type' : 'formula',
'criteria' : '=$F$7<=0',
'format' : f_condicion2
})
for col_num, value in enumerate(dfR.columns.values):
worksheet.write(5, col_num + 1, value, f_cabeceras)
worksheet.conditional_format('B7:N' + str(i),
{'type': 'cell',
'criteria': '<>',
'value': '""',
'format': f_bordes})
worksheet.set_portrait()
worksheet.set_paper(1)
worksheet.center_horizontally()
#worksheet.center_vertically()
worksheet.repeat_rows(0, 5)
worksheet.print_area('B7:G' + str(i))
worksheet.fit_to_pages(1, 0)
#worksheet.hide_gridlines(0)
worksheet.set_header('&LCIEC Cuotas, Ingresos y Egresos Condominales &Rciec.adanisoft.com')
worksheet.set_footer('&CPágina &P de &N &RImpreso el &D')
writer.close()
return filename.getvalue()
def run_detalle_ingresos_egresos(fecha_inicial, fecha_final, filename):
consulta = '''
select min(fecha_movimiento) as fecha_inicio,
max(fecha_movimiento) as fecha_fin,
count(cc.num_cuenta) as cuantos,
cc.num_cuenta as cuenta,
cc.descripcion as conepto,
comentario as subconcepto,
case when sum(m.deposito) > 0 then sum(d.monto) else 0 end as deposito,
case when sum(m.retiro) > 0 then sum(d.monto) else 0 end as retiro
from condominio_coyoacan_detalle_movimiento d,
condominio_coyoacan_movimiento m,
cuenta_contable cc
where d.movimiento_id = m.id
and d.cuenta_contable_id = cc.id
and m.fecha_movimiento >= '{ini}'
and m.fecha_movimiento <= '{fin}'
group by cc.descripcion, comentario, cc.num_cuenta order by 4,5,6
'''
consulta = consulta.format(ini = fecha_inicial.strftime('%Y-%m-%d'), fin = fecha_final.strftime('%Y-%m-%d'))
rows = execsql(consulta)
df = pd.DataFrame(rows)
df['deposito'] = df['deposito'].astype(float)
df['retiro'] = df['retiro'].astype(float)
df = df.drop(columns = ['cuenta'])
df = df.rename(columns = { 'fecha_inicio': 'Fecha inicio',
'fecha_fin' : 'Fecha final',
'cuantos' : 'Cantidad',
'concepto' : 'Concepto',
'subconcepto' : 'subConcepto',
'deposito' : 'Deposito',
'retiro' : 'Retiro'
})
writer = pd.ExcelWriter(filename, engine='xlsxwriter', datetime_format='dd/mm/yyyy', date_format='dd/mm/yyyy')
titulo = "CONDOMINIO COYOACAN 1045"
subtitulo = "DETALLE DE INGRESOS Y EGRESOS DESDE EL {} HASTA EL {}".format(fecha_inicial.strftime('%d/%m/%Y'), fecha_final.strftime('%d/%m/%Y'))
dfR = df.rename_axis(None)
dfR.to_excel(writer, sheet_name = 'HOJA', startrow = 5)
i = len(dfR.index) + 10
j = len(dfR.index) + 7
workbook = writer.book
worksheet = writer.sheets['HOJA']
#
f_titulos = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter'})
f_celdas = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
f_bordes = workbook.add_format({'bottom': 1})
f_descripcion = workbook.add_format({'align': 'left', 'valign': 'vjustify'})
f_numeros = workbook.add_format({'num_format': '#,##0.00', 'valign': 'vcenter'})
f_fechas = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'dd/mmm/yyyy' })
f_cabeceras = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top', 'align' : 'center', 'fg_color': '#D7E4BC', 'border': 1})
f_condicion1 = workbook.add_format({'bold': True, 'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
f_condicion2 = workbook.add_format({'bold': True, 'bg_color': '#C6EFCE', 'font_color': '#006100'})
f_ocultar = workbook.add_format({'font_color': '#FFFFFF'})
worksheet.set_column('B:C', 15, f_fechas )
worksheet.set_column('G:H', 15, f_numeros )
worksheet.set_column('E:E', 40)
worksheet.set_column('F:F', 20)
worksheet.set_column('D:D', 10, f_celdas)
worksheet.merge_range('B2:I2', titulo, f_titulos)
worksheet.merge_range('B3:I3', subtitulo, f_titulos)
worksheet.write('G' + str(j), '=SUM(G7:G{row})'.format(row=j-1))
worksheet.write('H' + str(j), '=SUM(H7:H{row})'.format(row=j-1))
for col_num, value in enumerate(dfR.columns.values):
worksheet.write(5, col_num + 1, value, f_cabeceras )
worksheet.conditional_format('B7:N' + str(i),
{'type': 'cell',
'criteria': '<>',
'value': '""',
'format': f_bordes})
worksheet.set_portrait()
worksheet.set_paper(1)
worksheet.center_horizontally()
#worksheet.center_vertically()
worksheet.repeat_rows(0, 5)
worksheet.print_area('B7:I' + str(i))
worksheet.fit_to_pages(1, 0)
#worksheet.hide_gridlines(0)
worksheet.set_header('&LCIEC Cuotas, Ingresos y Egresos Condominales &Rciec.adanisoft.com')
worksheet.set_footer('&CPágina &P de &N &RImpreso el &D')
writer.close()
return filename.getvalue()
def run_acum_coyoacan(condominio, shortname):
print(" generando acumulados %s " % shortname)
with transaction.atomic():
borrado = ''
nq1 = ''
nq2 = ''
#
# Borra acumulados
if shortname == "COYOACAN":
borrado = 'delete from condominio_coyoacan_acumulado_mes'
nq1 = '''
select nombre, clabe as cuenta, cb.saldo_inicial, min(fecha_movimiento) as fecha
from condominio_coyoacan_movimiento m,
condominio_coyoacan_cuenta_banco cb,
periodo_corte p,
condominio c
where cb.id = m.cuenta_banco_id
and m.fecha_movimiento >= p.fecha_inicial
and m.fecha_movimiento <= p.fecha_final
and c.nombre = 'COYOACAN'
and p.id = 10
group by 1,2,3
order by 4,2
'''
nq2 = '''
select 'Condominio' as nombre, clabe as cuenta, to_char(fecha_movimiento,'MM-YYYY') as mes,
min(fecha_movimiento) as fec_ini,
max(fecha_movimiento) as fec_fin,
round(sum(deposito),2) as depositos,
round(sum(retiro),2) as retiros,
round(sum(deposito)-sum(retiro),2) as diferencia
from condominio_coyoacan_movimiento m,
condominio_coyoacan_cuenta_banco cb,
periodo_corte p
where cb.id = m.cuenta_banco_id
and fecha_movimiento >= p.fecha_inicial
and fecha_movimiento <= p.fecha_final
and p.id = 10
group by 1,2,3
order by 2,4,3
'''
#print(borrado,nq1,nq2)
n = execsql(borrado)
#
# Trae saldo inicial de cada cuenta
saldo_condominio = 0
rows = execsql(nq1)
print(rows)
#
# Por cada cuenta
for r in rows:
saldo = float(r['saldo_inicial'])
#
# Agrega depositos y retiros por cuenta y mes
rows2 = execsql(nq2)
for r2 in rows2:
if r2['cuenta'] == r['cuenta']:
saldo = round(saldo + float(r2['depositos']) - float(r2['retiros']), 2)
print(r2['cuenta'], r2['mes'], r2['depositos'], r2['retiros'], saldo)
reg = AcumuladoMes(cuenta_banco=r2['cuenta'], \
mes=r2['mes'], \
fecha_inicial=r2['fec_ini'], \
fecha_final=r2['fec_fin'], \
depositos=r2['depositos'], \
retiros=r2['retiros'], \
saldo=saldo)
reg.save()
if r['cuenta'] != '000000000000000000':
saldo_condominio = saldo_condominio + saldo
# print(saldo_condominio)
#
# Actualiza saldo en periodos
oPer = PeriodoCorte.objects.get(id=10)
oPer.saldo_final = saldo_condominio
oPer.save()
def run_determinacionSaldos_coyoacan(condomino):
print(" determinando saldos %s " % condomino.depto)
with transaction.atomic():
# tipo = TipoMovimiento.objects.get(id=21)
# prop = TipoMovimiento.objects.get(id=30)
cuenta = CuentaContable.objects.get(id=82)
# prove = Proveedore.objects.get(id=1)
#
# Borra asientos
n = execsql('delete from condominio_coyoacan_registro where condomino_id = %s' % condomino.id)
#
# Agrega adeudo inicial
if not condomino.depto == '0000':
ade = condomino.adeudo_inicial
sal = 0
deb = 0
sal = sal + deb - ade
# adeudo = condomino.adeudo_inicial
reg_i = Registro(fecha=condomino.fecha_adeudo_inicial, \
descripcion='SALDO INICIAL A LA FECHA', \
debe=deb, \
haber=ade, \
saldo=sal, \
cuenta_contable=cuenta, \
condomino=condomino)
reg_i.save()
#
# Agrega adeudos por cuotas
rows = CuotasCondominio.objects.all().order_by('mes_inicial')
for r in rows:
delta = (r.mes_final - r.mes_inicial)
# print(r.descripcion,r.mes_inicial,r.mes_final,r.monto,r.cuenta_contable,delta.days)
condom = r.condomino.filter(depto__contains=condomino.depto)
if condom:
base = r.mes_inicial
for x in range(0, delta.days + 1):
fecha = base + timedelta(days=x)
if fecha.day == 1:
reg_a = Registro(fecha=fecha, \
descripcion='CARGO {}'.format(r.descripcion), \
debe=0, \
haber=r.monto, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_a.save()
#
# Agrega depositos por movimiento de banco
if not condomino.depto == '0000':
movtos = Movimiento.objects.filter(condomino__id=condomino.id).order_by('fecha_movimiento', 'id')
for m in movtos:
reg_m = Registro(fecha=m.fecha_movimiento, \
descripcion=m.descripcion, \
debe=m.deposito, \
haber=0, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_m.save()
asientos = Asiento.objects.filter(condomino_id=condomino.id).order_by('fecha', 'id')
for a in asientos:
reg_a = Registro(fecha=a.fecha, \
descripcion=a.descripcion, \
debe=a.debe, \
haber=a.haber, \
saldo=a.saldo, \
cuenta_contable=a.cuenta_contable, \
condomino=condomino)
reg_a.save()
# Recalcula saldos
if not condomino.depto == '0000':
sal = 0
car = 0
dep = 0
rec = Registro.objects.filter(condomino__id=condomino.id).order_by('fecha', 'id')
for rr in rec:
car = car + rr.haber
dep = dep + rr.debe
sal = sal + rr.haber - rr.debe
rr.saldo = sal
rr.save()
reg_c = Condomino.objects.get(id=condomino.id)
reg_c.cargos = car
reg_c.abonos = dep
reg_c.saldo = sal
reg_c.save()

View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

View File

View File

@@ -0,0 +1,181 @@
from django.contrib import admin
from .models import Movimiento, DetalleMovimiento, CuentaBanco, CuotasCondominio, Condomino, AcumuladoMes, Registro, MovSinIdent, Asiento
from .procesos import run_determinacionSaldos_sadi81Nvo
from catalogos.models import PeriodoCorte
from django.utils.safestring import mark_safe
# Register your models here.
class DetalleMovtoInline(admin.TabularInline):
model = DetalleMovimiento
fields = ['cuenta_contable', 'monto', 'comentario']
def get_extra(self, request, obj=None, **kwargs):
extra = 4
return extra
@admin.register(Movimiento)
class MovtoAdmin(admin.ModelAdmin):
list_display = ('id','fecha_movimiento','descripcion','retiros','depositos','condomino', 'conciliacion')
search_fields = ('descripcion',)
date_hierarchy = 'fecha_movimiento'
ordering = ('-fecha_movimiento',)
save_on_top = True
inlines = [DetalleMovtoInline]
def retiros(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiro)
def depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.deposito)
def conciliacion(self, request, obj=None, **kwargs):
cantidades = DetalleMovimiento.objects.filter(movimiento_id=request.id).values_list('monto', flat=True)
total = sum(cantidades)
if (total != (request.retiro + request.deposito)):
return False
else:
return True
conciliacion.boolean = True
@admin.register(CuentaBanco)
class CuentaBancoAdmin(admin.ModelAdmin):
list_display = ('banco','clabe','apoderado')
@admin.register(CuotasCondominio)
class CuotasAdmin(admin.ModelAdmin):
list_display = ('descripcion', 'mes_inicial', 'mes_final', 'cantidad','cuenta_contable')
ordering = ('-mes_inicial',)
actions = ['cambiofechas',]
def cantidad(self, request, obj=None, **kwargs):
return "{:,}".format(request.monto)
def cambiofechas(self, request, queryset):
# condominio "SADI81NVO" tiene el id 9
oPer = PeriodoCorte.objects.get(id=9)
fecha_corte = oPer.fecha_final
#print(fecha_corte)
for obj in queryset:
id = "%s" % obj.id
obj.mes_final = fecha_corte
obj.save()
self.message_user(request, " Fin del proceso de cambio de fechas ")
cambiofechas.short_description = "Cambio de fecha de corte de cuotas "
@admin.register(Condomino)
class CondominoAdmin(admin.ModelAdmin):
list_display = ('depto', 'poseedor', 'adeudo_inicio', 'cuotas', 'depositos', 'adeudo_actual')
search_fields = ('depto', 'propietario', 'poseedor')
actions = ['determina_saldos']
def adeudo_inicio(self, request, obj=None, **kwargs):
return "{:,}".format(request.adeudo_inicial)
def cuotas(self, request, obj=None, **kwargs):
cargos = request.cargos - request.adeudo_inicial
return "{:,}".format(cargos)
def depositos(self, request, obj=None, **kwargs):
pagos = request.abonos
return "{:,}".format(pagos)
def adeudo_actual(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def determina_saldos(self, request, queryset):
for obj in queryset:
# print(" determina saldos %s " % obj.depto)
run_determinacionSaldos_sadi81Nvo(obj)
#pass
self.message_user(request, " Fin del proceso de determinacion de saldos ")
determina_saldos.short_description = "Determinacion de Saldos"
@admin.register(AcumuladoMes)
class AcumuladoAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'mes', 'fecha_inicial', 'fecha_final', 'Depositado', 'Retirado', 'Saldos')
ordering = ('-fecha_inicial', 'cuenta_banco',)
#actions = ['export_as_csv']
#change_list_template = "admin/titulo_acumulados.html"
def Depositado(self, request, obj=None, **kwargs):
return "{:,}".format(request.depositos)
def Retirado(self, request, obj=None, **kwargs):
return "{:,}".format(request.retiros)
def Saldos(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
class dontLog:
def log_deletion(self, **kwargs):
return
@admin.register(Asiento)
class AsientoAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','descripcion','condomino','Cargos','Depositos','Saldo')
#change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
#@admin.register(Registro)
class RegistroAdmin(dontLog, admin.ModelAdmin):
list_display = ('fecha','E','descripcion','Cargos','Depositos','Saldo')
change_list_template = "admin/titulo_registros.html"
ordering = ('-fecha','-id')
def Depositos(self, request, obj=None, **kwargs):
return "{:,}".format(request.debe)
def Cargos(self, request, obj=None, **kwargs):
return "{:,}".format(request.haber)
def Saldo(self, request, obj=None, **kwargs):
return "{:,}".format(request.saldo)
def E(self, request, obj=None, **kwargs):
icon = '''
<svg width="16" height="16" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="right">
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
</g>
</defs>
<use xlink:href="#right" x="0" y="0" fill="#447e9b" />
</svg>
'''
#text = format_html('<img src="{}" alt="view">', icon)
if(request.debe > 0):
#return _boolean_icon(True)
return mark_safe('%s' % icon)
else:
return ""
E.allow_tags = True
@admin.register(MovSinIdent)
class MovSinIdentAdmin(admin.ModelAdmin):
list_display = ('cuenta_banco', 'fecha_movimiento', 'descripcion', 'deposito')
date_hierarchy = 'fecha_movimiento'
save_on_top = True
inlines = [DetalleMovtoInline]
ordering = ('-fecha_movimiento',)
def get_queryset(self, request):
query = super(MovSinIdentAdmin, self).get_queryset(request)
filtered_query = query.filter(condomino__depto='0000').exclude(retiro__gt=0)
return filtered_query

View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CondominioSadiCarnot81NvoConfig(AppConfig):
name = 'condominio_sadicarnot81_Nvo'

View File

@@ -0,0 +1,179 @@
from django.db import models
from django.db.models import Q
from catalogos.models import Banco, CuentaContable
from django.utils.safestring import mark_safe
from django.templatetags.static import static
from django.utils.html import format_html
# Create your models here.
class CuentaBanco(models.Model):
banco = models.ForeignKey(Banco, related_name='condominio_321', on_delete=models.PROTECT)
clabe = models.CharField(max_length=18)
apoderado = models.CharField(max_length=60)
saldo_inicial = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_inicial = models.DateField(blank=True, null=True)
saldo_final = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=0)
fecha_saldo_final = models.DateField(blank=True, null=True)
def __str__(self):
return '%s %s %d' % (self.clabe, self.apoderado[:10], self.saldo_final)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_cuenta_banco'
verbose_name_plural = "Cuentas bancarias"
class Condomino(models.Model):
depto = models.CharField(max_length=15, blank=True, null=True)
propietario = models.CharField(max_length=60, blank=True, null=True)
poseedor = models.CharField(max_length=60, blank=True, null=True)
ubicacion = models.CharField(max_length=20, blank=True, null=True)
email = models.CharField(max_length=25, blank=True, null=True)
telefono = models.CharField(max_length=30, blank=True, null=True)
fecha_escrituracion = models.DateField(blank=True, null=True)
referencia = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
indiviso = models.DecimalField(max_digits=10, decimal_places=4, blank=True, null=True)
adeudo_inicial = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
fecha_adeudo_inicial = models.DateField(blank=True, null=True)
cargos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
abonos = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return '%s %s' % (self.depto, self.poseedor)
def estado_cuenta(self):
icon_url = static('admin/img/icon-viewlink.svg')
text = format_html('<img src="{}" alt="view">', icon_url)
return mark_safe(
'<a href="/api-rest/estadocuenta/sadi81nvo/%d">%s</a>' % (
self.id, text))
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_condomino'
ordering = ['depto']
class Movimiento(models.Model):
cuenta_banco = models.ForeignKey(CuentaBanco, default=1,related_name='condominio_322', on_delete=models.PROTECT)
fecha_movimiento = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
deposito = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
retiro = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
condomino = models.ForeignKey(Condomino, related_name='condominio_323', on_delete=models.PROTECT)
def __str__(self):
return u'%d %s %d %s' % (
self.id, self.fecha_movimiento.strftime('%d/%m/%Y'), self.deposito, self.descripcion[:15])
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_movimiento'
ordering = ['fecha_movimiento']
class DetalleMovimiento(models.Model):
movimiento = models.ForeignKey(Movimiento, verbose_name=('Movto'), related_name='condominio_324', on_delete=models.CASCADE)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable Ingreso/Egreso'),
related_name='condominio_325',
on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='41') | Q(clave_mayor='51') | Q(
num_cuenta='2318'))
comentario = models.CharField(max_length=20, blank=True, null=True, default=".")
def __str__(self):
return '%s %d' % (self.cuenta_contable, self.monto)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_detalle_movimiento'
ordering = ['movimiento']
class Registro(models.Model):
condomino = models.ForeignKey(Condomino, default=1, related_name='condominio_326', on_delete=models.PROTECT)
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='condominio_327', on_delete=models.CASCADE,
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_registro'
ordering = ['fecha']
verbose_name_plural = "Registros"
class Asiento(models.Model):
condomino = models.ForeignKey(Condomino, default=1, on_delete=models.PROTECT, related_name='condominio_396')
fecha = models.DateField(blank=True, null=True)
descripcion = models.CharField(max_length=250, blank=True, null=True)
debe = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0,
verbose_name='Depositos')
haber = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0, verbose_name='Cargos')
saldo = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), on_delete=models.CASCADE, related_name='condominio_397',
limit_choices_to=Q(clave_mayor='23'))
def __str__(self):
return u'%d %s %d %d %d' % (self.id, self.fecha.strftime('%d/%m/%Y'), self.debe, self.haber, self.saldo)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_asiento'
ordering = ['fecha']
verbose_name_plural = "Auxiliar"
class CuotasCondominio(models.Model):
descripcion = models.CharField(max_length=30, blank=True, null=True)
mes_inicial = models.DateField(blank=True, null=True)
mes_final = models.DateField(blank=True, null=True)
dia_vencimiento = models.DecimalField(max_digits=2, decimal_places=0, blank=True, null=True, default=1)
monto = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0)
cuenta_contable = models.ForeignKey(CuentaContable, verbose_name=('Cuenta Contable'), related_name='condominio_328', on_delete=models.CASCADE)
condomino = models.ManyToManyField(Condomino, related_name='condominio_329')
def __str__(self):
return u'%s %s %s %d %s' % (
self.descripcion, self.mes_inicial.strftime('%m-%Y'), self.mes_final.strftime('%m-%Y'), self.monto,
self.cuenta_contable)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_cuotas'
ordering = ['mes_inicial']
verbose_name_plural = "Cuotas"
class AcumuladoMes(models.Model):
cuenta_banco = models.CharField(max_length=20, blank=True, null=True)
mes = models.CharField(max_length=7, blank=True, null=True)
fecha_inicial = models.DateField(blank=True, null=True)
fecha_final = models.DateField(blank=True, null=True)
depositos = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
retiros = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
saldo = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True, default=0)
def __str__(self):
return u'%s %s %s %s %d %d %d' % (
self.cuenta_banco, self.mes, self.fecha_inicial.strftime('%d/%m/%Y'), self.fecha_final.strftime('%d/%m/%Y'),
self.depositos, self.retiros, self.saldo)
class Meta:
managed = True
db_table = 'condominio_sadi81nvo_acumulado_mes'
verbose_name_plural = "Depositos y retiros por mes"
class MovSinIdent(Movimiento):
class Meta:
proxy = True
verbose_name = 'Deposito sin identificar'
verbose_name_plural = 'Depositos sin identificar'

View File

@@ -0,0 +1,178 @@
from django.db import transaction
from django.db import connection
from .models import AcumuladoMes, Registro, CuotasCondominio, Movimiento, Condomino, CuentaBanco, Asiento
from catalogos.models import CuentaContable, PeriodoCorte
from ciec.procesos import dictfetchall, execsql
from datetime import datetime, timedelta
def run_acum_sadi81Nvo(condominio, shortname):
print(" generando acumulados %s " % shortname)
with transaction.atomic():
borrado = ''
nq1 = ''
nq2 = ''
#
# Borra acumulados
if shortname == "SADI81NVO":
borrado = ''' delete from condominio_sadi81nvo_acumulado_mes '''
nq1 = '''
select nombre, clabe as cuenta, cb.saldo_inicial, min(fecha_movimiento) as fecha
from condominio_sadi81nvo_movimiento m,
condominio_sadi81nvo_cuenta_banco cb,
periodo_corte p,
condominio c
where cb.id = m.cuenta_banco_id
and m.fecha_movimiento >= p.fecha_inicial
and m.fecha_movimiento <= p.fecha_final
and c.nombre = 'SADI81NVO'
and p.id = 9
group by 1,2,3
order by 4,2
'''
nq2 = '''
select 'Condominio' as nombre, clabe as cuenta, to_char(fecha_movimiento,'MM-YYYY') as mes,
min(fecha_movimiento) as fec_ini,
max(fecha_movimiento) as fec_fin,
round(sum(deposito),2) as depositos,
round(sum(retiro),2) as retiros,
round(sum(deposito)-sum(retiro),2) as diferencia
from condominio_sadi81nvo_movimiento m,
condominio_sadi81nvo_cuenta_banco cb,
periodo_corte p
where cb.id = m.cuenta_banco_id
and fecha_movimiento >= p.fecha_inicial
and fecha_movimiento <= p.fecha_final
and p.id = 9
group by 1,2,3
order by 2,4,3
'''
#print(borrado,nq1,nq2)
n = execsql(borrado)
#
# Trae saldo inicial de cada cuenta
saldo_condominio = 0
rows = execsql(nq1)
print(rows)
#
# Por cada cuenta
for r in rows:
saldo = float(r['saldo_inicial'])
#
# Agrega depositos y retiros por cuenta y mes
rows2 = execsql(nq2)
for r2 in rows2:
if r2['cuenta'] == r['cuenta']:
saldo = round(saldo + float(r2['depositos']) - float(r2['retiros']), 2)
print(r2['cuenta'], r2['mes'], r2['depositos'], r2['retiros'], saldo)
reg = AcumuladoMes(cuenta_banco=r2['cuenta'], \
mes=r2['mes'], \
fecha_inicial=r2['fec_ini'], \
fecha_final=r2['fec_fin'], \
depositos=r2['depositos'], \
retiros=r2['retiros'], \
saldo=saldo)
reg.save()
if r['cuenta'] != '000000000000000000':
saldo_condominio = saldo_condominio + saldo
# print(saldo_condominio)
#
# Actualiza saldo en periodos
oPer = PeriodoCorte.objects.get(id=9)
oPer.saldo_final = saldo_condominio
oPer.save()
def run_determinacionSaldos_sadi81Nvo(condomino):
print(" determinando saldos %s " % condomino.depto)
with transaction.atomic():
# tipo = TipoMovimiento.objects.get(id=21)
# prop = TipoMovimiento.objects.get(id=30)
cuenta = CuentaContable.objects.get(id=82)
# prove = Proveedore.objects.get(id=1)
#
# Borra asientos
n = execsql(''' delete from condominio_sadi81nvo_registro where condomino_id = %s ''' % condomino.id)
#
# Agrega adeudo inicial
if not condomino.depto == '0000':
ade = condomino.adeudo_inicial
sal = 0
deb = 0
sal = sal + deb - ade
# adeudo = condomino.adeudo_inicial
reg_i = Registro(fecha=condomino.fecha_adeudo_inicial, \
descripcion='SALDO INICIAL A LA FECHA', \
debe=deb, \
haber=ade, \
saldo=sal, \
cuenta_contable=cuenta, \
condomino=condomino)
reg_i.save()
#
# Agrega adeudos por cuotas
rows = CuotasCondominio.objects.all().order_by('mes_inicial')
for r in rows:
delta = (r.mes_final - r.mes_inicial)
# print(r.descripcion,r.mes_inicial,r.mes_final,r.monto,r.cuenta_contable,delta.days)
condom = r.condomino.filter(depto__contains=condomino.depto)
if condom:
base = r.mes_inicial
for x in range(0, delta.days + 1):
fecha = base + timedelta(days=x)
if fecha.day == 1:
reg_a = Registro(fecha=fecha, \
descripcion='CARGO {}'.format(r.descripcion), \
debe=0, \
haber=r.monto, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_a.save()
#
# Agrega depositos por movimiento de banco
if not condomino.depto == '0000':
movtos = Movimiento.objects.filter(condomino__id=condomino.id).order_by('fecha_movimiento', 'id')
for m in movtos:
reg_m = Registro(fecha=m.fecha_movimiento, \
descripcion=m.descripcion, \
debe=m.deposito, \
haber=0, \
saldo=0, \
cuenta_contable=r.cuenta_contable, \
condomino=condomino)
reg_m.save()
asientos = Asiento.objects.filter(condomino_id=condomino.id).order_by('fecha', 'id')
for a in asientos:
reg_a = Registro(fecha=a.fecha, \
descripcion=a.descripcion, \
debe=a.debe, \
haber=a.haber, \
saldo=a.saldo, \
cuenta_contable=a.cuenta_contable, \
condomino=condomino)
reg_a.save()
# Recalcula saldos
if not condomino.depto == '0000':
sal = 0
car = 0
dep = 0
rec = Registro.objects.filter(condomino__id=condomino.id).order_by('fecha', 'id')
for rr in rec:
car = car + rr.haber
dep = dep + rr.debe
sal = sal + rr.haber - rr.debe
rr.saldo = sal
rr.save()
reg_c = Condomino.objects.get(id=condomino.id)
reg_c.cargos = car
reg_c.abonos = dep
reg_c.saldo = sal
reg_c.save()

View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

22
manage.py Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ciec.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()