commit c04ee70afc9f5ab37feafb0a5a102ed8d5c4c6ec Author: root Date: Sun Dec 21 15:14:34 2025 -0600 inicial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c555ddf --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.log +*.pot +*.pyc +*.bak +*.bk +*.xlsx +*.pdf + +db.sqlite3 + +__pycache__/ +staticfiles +media +**/migrations/* +/modeler/.config +outputs/ +bin/ +include/ +lib/ diff --git a/catalogos/__init__.py b/catalogos/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/catalogos/admin.py b/catalogos/admin.py new file mode 100755 index 0000000..31b64aa --- /dev/null +++ b/catalogos/admin.py @@ -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" + + diff --git a/catalogos/apps.py b/catalogos/apps.py new file mode 100755 index 0000000..2f2b913 --- /dev/null +++ b/catalogos/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CatalogosConfig(AppConfig): + name = 'catalogos' diff --git a/catalogos/models.py b/catalogos/models.py new file mode 100755 index 0000000..abb2726 --- /dev/null +++ b/catalogos/models.py @@ -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" diff --git a/catalogos/tests.py b/catalogos/tests.py new file mode 100755 index 0000000..7ce503c --- /dev/null +++ b/catalogos/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/catalogos/views.py b/catalogos/views.py new file mode 100755 index 0000000..3083571 --- /dev/null +++ b/catalogos/views.py @@ -0,0 +1,5 @@ +from django.http import HttpResponseRedirect + +def home(request): + return HttpResponseRedirect('/5up3rc4l1fr4ct1c03sp1r4l1d0s0') + diff --git a/ciec/__init__.py b/ciec/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/ciec/asgi.py b/ciec/asgi.py new file mode 100755 index 0000000..57ad654 --- /dev/null +++ b/ciec/asgi.py @@ -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() diff --git a/ciec/procesos.py b/ciec/procesos.py new file mode 100755 index 0000000..68a8201 --- /dev/null +++ b/ciec/procesos.py @@ -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 + + diff --git a/ciec/settings.py b/ciec/settings.py new file mode 100755 index 0000000..51106b2 --- /dev/null +++ b/ciec/settings.py @@ -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' + + diff --git a/ciec/urls.py b/ciec/urls.py new file mode 100755 index 0000000..d1c238f --- /dev/null +++ b/ciec/urls.py @@ -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) + diff --git a/ciec/wsgi.py b/ciec/wsgi.py new file mode 100755 index 0000000..3bff496 --- /dev/null +++ b/ciec/wsgi.py @@ -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() diff --git a/condominio_aragon_37/__init__.py b/condominio_aragon_37/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/condominio_aragon_37/admin.py b/condominio_aragon_37/admin.py new file mode 100755 index 0000000..c23482f --- /dev/null +++ b/condominio_aragon_37/admin.py @@ -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 = ''' + + + + + + + + + ''' + #text = format_html('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 diff --git a/condominio_aragon_37/apps.py b/condominio_aragon_37/apps.py new file mode 100755 index 0000000..64647a5 --- /dev/null +++ b/condominio_aragon_37/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CondominioAragon37Config(AppConfig): + name = 'condominio_aragon_37' diff --git a/condominio_aragon_37/models.py b/condominio_aragon_37/models.py new file mode 100755 index 0000000..f65a02f --- /dev/null +++ b/condominio_aragon_37/models.py @@ -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('view', icon_url) + return mark_safe( + '%s' % ( + 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' diff --git a/condominio_aragon_37/procesos.py b/condominio_aragon_37/procesos.py new file mode 100755 index 0000000..16fdf65 --- /dev/null +++ b/condominio_aragon_37/procesos.py @@ -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() + + diff --git a/condominio_balcones/__init__.py b/condominio_balcones/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/condominio_balcones/admin.py b/condominio_balcones/admin.py new file mode 100755 index 0000000..403eeb9 --- /dev/null +++ b/condominio_balcones/admin.py @@ -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 = ''' + + + + + + + + + ''' + #text = format_html('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 diff --git a/condominio_balcones/apps.py b/condominio_balcones/apps.py new file mode 100755 index 0000000..6781ebf --- /dev/null +++ b/condominio_balcones/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CondominioBalconesConfig(AppConfig): + name = 'condominio_balcones' diff --git a/condominio_balcones/models.py b/condominio_balcones/models.py new file mode 100755 index 0000000..3d4e27c --- /dev/null +++ b/condominio_balcones/models.py @@ -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('view', icon_url) + return mark_safe( + '%s' % ( + 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' + diff --git a/condominio_balcones/procesos.py b/condominio_balcones/procesos.py new file mode 100755 index 0000000..abda942 --- /dev/null +++ b/condominio_balcones/procesos.py @@ -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() + + diff --git a/condominio_balcones/tests.py b/condominio_balcones/tests.py new file mode 100755 index 0000000..7ce503c --- /dev/null +++ b/condominio_balcones/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/condominio_balcones/views.py b/condominio_balcones/views.py new file mode 100755 index 0000000..e69de29 diff --git a/condominio_coyoacan/__init__.py b/condominio_coyoacan/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/condominio_coyoacan/admin.py b/condominio_coyoacan/admin.py new file mode 100644 index 0000000..0e988cf --- /dev/null +++ b/condominio_coyoacan/admin.py @@ -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 = ''' + + + + + + + + + ''' + #text = format_html('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 diff --git a/condominio_coyoacan/apps.py b/condominio_coyoacan/apps.py new file mode 100644 index 0000000..863f4a0 --- /dev/null +++ b/condominio_coyoacan/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CondominioMatiasRomeroConfig(AppConfig): + name = 'condominio_coyoacan' diff --git a/condominio_coyoacan/models.py b/condominio_coyoacan/models.py new file mode 100644 index 0000000..00ef79a --- /dev/null +++ b/condominio_coyoacan/models.py @@ -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('view', icon_url) + return mark_safe( + '%s' % ( + 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' + diff --git a/condominio_coyoacan/procesos.py b/condominio_coyoacan/procesos.py new file mode 100644 index 0000000..354dfa4 --- /dev/null +++ b/condominio_coyoacan/procesos.py @@ -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() + + diff --git a/condominio_coyoacan/tests.py b/condominio_coyoacan/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/condominio_coyoacan/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/condominio_coyoacan/views.py b/condominio_coyoacan/views.py new file mode 100644 index 0000000..e69de29 diff --git a/condominio_sadicarnot81_Nvo/__init__.py b/condominio_sadicarnot81_Nvo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/condominio_sadicarnot81_Nvo/admin.py b/condominio_sadicarnot81_Nvo/admin.py new file mode 100644 index 0000000..bc55e41 --- /dev/null +++ b/condominio_sadicarnot81_Nvo/admin.py @@ -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 = ''' + + + + + + + + + ''' + #text = format_html('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 diff --git a/condominio_sadicarnot81_Nvo/apps.py b/condominio_sadicarnot81_Nvo/apps.py new file mode 100644 index 0000000..2fabf02 --- /dev/null +++ b/condominio_sadicarnot81_Nvo/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CondominioSadiCarnot81NvoConfig(AppConfig): + name = 'condominio_sadicarnot81_Nvo' diff --git a/condominio_sadicarnot81_Nvo/models.py b/condominio_sadicarnot81_Nvo/models.py new file mode 100644 index 0000000..ffb77a4 --- /dev/null +++ b/condominio_sadicarnot81_Nvo/models.py @@ -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('view', icon_url) + return mark_safe( + '%s' % ( + 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' + diff --git a/condominio_sadicarnot81_Nvo/procesos.py b/condominio_sadicarnot81_Nvo/procesos.py new file mode 100644 index 0000000..7680543 --- /dev/null +++ b/condominio_sadicarnot81_Nvo/procesos.py @@ -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() + + diff --git a/condominio_sadicarnot81_Nvo/tests.py b/condominio_sadicarnot81_Nvo/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/condominio_sadicarnot81_Nvo/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/condominio_sadicarnot81_Nvo/views.py b/condominio_sadicarnot81_Nvo/views.py new file mode 100644 index 0000000..e69de29 diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..a7857dd --- /dev/null +++ b/manage.py @@ -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()