inicio del repo

This commit is contained in:
jburgos
2026-05-13 13:45:56 +00:00
parent 4233c697d5
commit e51e379440
13 changed files with 323 additions and 0 deletions

0
__init__.py Normal file
View File

6
apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ResumenConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'resumen'

View File

@@ -0,0 +1,46 @@
define([
'knockout',
'arches',
'js-cookie',
'templates/views/components/plugins/resumen.htm'
], function(ko, arches, Cookies, ResumenTemplate) {
const ResumenViewModel = function() {
const self = this;
this.loading = ko.observable(true);
this.records = ko.observable();
this.getStatus = async function() {
const response = await window.fetch("resumen");
const data = await response.json();
self.bMueblesCount = data.b_muebles_count;
self.bInmueblesCount = data.b_inmuebles_count;
self.inmaterialCount = data.inmaterial_count;
self.sitiosArqCount = data.sitios_arq_count;
self.actoresCount = data.actores_count;
self.digitalesCount = data.digitales_count;
self.actividadesCount = data.actividades_count;
self.records(data.records);
self.loading(false);
};
this.saveStatus = async function() {
const response = await fetch("resumen", {
method: 'POST',
credentials: 'include',
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
}
});
const data = await response.json();
self.records(data.records);
};
this.getStatus();
};
return ko.components.register('resumen', {
viewModel: ResumenViewModel,
template: ResumenTemplate
});
});

View File

@@ -0,0 +1,36 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
]
forward = """
CREATE OR REPLACE VIEW resumen AS
SELECT g.name->>'es' AS modelo, COALESCE(COUNT(ri.resourceinstanceid),0) AS Cuenta
FROM graphs AS g LEFT JOIN resource_instances AS ri ON g.graphid = ri.graphid
WHERE g.isresource AND g.name ? 'es'
GROUP BY g.name;
"""
reverse = """
DROP VIEW IF EXISTS resumen;
DELETE FROM system_record;
"""
operations = [
migrations.CreateModel(
name='SystemRecord',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('state_details', models.JSONField(blank=True, null=True)),
('state_time', models.DateTimeField(auto_now_add=True)),
],
options={
'db_table': 'system_record',
'managed': True,
},
),
migrations.RunSQL(forward, reverse),
]

0
migrations/__init__.py Normal file
View File

11
models.py Normal file
View File

@@ -0,0 +1,11 @@
from django.db import models
from django.db.models import JSONField
class SystemRecord(models.Model):
state_details = JSONField(blank=True, null=True)
state_time = models.DateTimeField(auto_now_add=True, blank=True)
class Meta:
managed = True
db_table = "system_record"

14
resumen.json Normal file
View File

@@ -0,0 +1,14 @@
{
"pluginid": "ba58b43b-5bd0-40f0-8876-78858a22cc77",
"name": "Resumen",
"icon": "fa fa-pie-chart",
"component": "views/components/plugins/resumen",
"componentname": "resumen",
"config": {
"show": true,
"is_workflow": false,
"description": "Resúmen estadístico de los registros patrimoniales"
},
"slug": "resumen",
"sortorder": 1
}

12
templates/arches_urls.htm Normal file
View File

@@ -0,0 +1,12 @@
{% extends "arches_urls.htm" %}
{% load static %}
{% load l10n %}
{% load i18n %}
{% block arches_urls %}
{{ block.super }}
<div class="arches-urls"
resumen = "{% url 'resumen' %}"
></div>
{% endblock arches_urls %}

View File

@@ -0,0 +1,123 @@
{% load i18n %}
<style>
h1 {
font-size: medium;
font-weight: 600;
}
h2 {
font-size: small;
font-weight: 600;
margin: 6px 0 3px;
}
.resumen-container {
background-color: #fff;
color: #386ea4;
border-style: solid 1px #eee;
display: flex;
flex-direction: row;
justify-content: center;
align-items: baseline;
width: 100%;
height: inherit;
padding-top: 25px;
}
.resumen-summary {
width: 320px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: left;
height: inherit;
padding: 0 20px;
}
.summary-item {
display: inline-flex;
justify-content: space-between;
align-items: baseline;
}
.resumen-history {
width: 320px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: left;
height: inherit;
padding: 20px 0;
}
.resumen-history-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.resumen-history-grid .history-item {
padding: 5px 0;
text-align: left;
}
</style>
<!--ko ifnot: $data.loading -->
<div class="resumen-container">
<div class="resumen-summary">
<h1>Resúmen estadístico</h1>
<div class="summary-item">
<h2>Bienes Muebles:</h2>
<div data-bind="text: $data.bMueblesCount"></div>
</div>
<div class="summary-item">
<h2>Bienes Inmuebles:</h2>
<div data-bind="text: $data.bInmueblesCount"></div>
</div>
<div class="summary-item">
<h2>Patrimonio Inmaterial:</h2>
<div data-bind="text: $data.inmaterialCount"></div>
</div>
<div class="summary-item">
<h2>Sitios arqueológicos:</h2>
<div data-bind="text: $data.sitiosArqCount"></div>
</div>
<div class="summary-item">
<h2>Organizaciones y Personas:</h2>
<div data-bind="text: $data.actoresCount"></div>
</div>
<div class="summary-item">
<h2>Adjuntos digitales:</h2>
<div data-bind="text: $data.digitalesCount"></div>
</div>
<div class="summary-item">
<h2>Actividades:</h2>
<div data-bind="text: $data.actividadesCount"></div>
</div>
<button class="btn btn-primary" style="width: fit-content; margin-top: 5px" data-bind="click: $data.saveStatus">Guardar resúmen actual</button>
<div class="resumen-history">
<h1>Historial de resúmenes</h1>
<div class="resumen-history-grid">
<h2 class="history-item">B. Muebles:</h2>
<h2 class="history-item">B. Inmuebles:</h2>
<h2 class="history-item">Inmaterial:</h2>
<h2 class="history-item">S. arqueológicos:</h2>
<h2 class="history-item">Org. y personas:</h2>
<h2 class="history-item">Adj. digitales:</h2>
<h2 class="history-item">Actividades:</h2>
<h2 class="history-item" style="width:135px">Guardado:</h2>
<!--ko foreach: $data.records -->
<div class="history-item" style="padding: 2px;" data-bind="text:$data.b_muebles"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.b_inmuebles"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.inmaterial"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.sitios_arq"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.actores"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.digitales"></div>
<div class="history-item" style="padding: 2px;" data-bind="text:$data.actividades"></div>
<div class="history-item" style="padding: 2px; width: 135px" data-bind="text:$data.statetime"></div>
<!--/ko -->
</div>
</div>
</div>
</div>
<!--/ko-->

3
tests.py Normal file
View File

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

6
urls.py Normal file
View File

@@ -0,0 +1,6 @@
from django.urls import re_path
from resumen.views.resumen import Resumen
urlpatterns = [
re_path(r"^resumen/", Resumen.as_view(), name="resumen"),
]

0
views/__init__.py Normal file
View File

66
views/resumen.py Normal file
View File

@@ -0,0 +1,66 @@
from django.utils.decorators import method_decorator
from django.views.generic import View
from django.views.decorators.csrf import csrf_exempt
from arches.app.models.models import ResourceInstance
from django.http import JsonResponse
from resumen.models import SystemRecord
@method_decorator(csrf_exempt, name="dispatch")
class Resumen(View):
def serialize_system_records(self):
res = [{
"b_muebles": v["state_details"]["b_muebles"],
"b_inmuebles": v["state_details"]["b_inmuebles"],
"inmaterial": v["state_details"]["inmaterial"],
"sitios_arq": v["state_details"]["sitios_arq"],
"actores": v["state_details"]["actores"],
"digitales": v["state_details"]["digitales"],
"actividades": v["state_details"]["actividades"],
"statetime": v["state_time"].strftime("%d/%m/%Y, %H:%M:%S")
} for v in SystemRecord.objects.all().values().order_by('-state_time')]
return res
def get(self, request):
data = {
"records": self.serialize_system_records(),
"b_muebles_count": ResourceInstance.objects.filter(graph_id='10b03fec-4d85-11ee-a708-ffcd06c08a5d').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='10b03fec-4d85-11ee-a708-ffcd06c08a5d').count(),int) else 0,
"b_inmuebles_count": ResourceInstance.objects.filter(graph_id='8ea3bf67-89ce-474c-b3cb-6dd5ee3d6198').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='8ea3bf67-89ce-474c-b3cb-6dd5ee3d6198').count(),int) else 0,
"inmaterial_count": ResourceInstance.objects.filter(graph_id='9b0e22c7-5c56-4be6-aa89-ae2632ba28e8').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='9b0e22c7-5c56-4be6-aa89-ae2632ba28e8').count(),int) else 0,
"sitios_arq_count": ResourceInstance.objects.filter(graph_id='76331d8a-4d85-11ee-a708-ffcd06c08a5d').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='76331d8a-4d85-11ee-a708-ffcd06c08a5d').count(),int) else 0,
"actores_count": ResourceInstance.objects.filter(graph_id='72420da0-db59-4048-aea2-03b0bc5cdcdf').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='72420da0-db59-4048-aea2-03b0bc5cdcdf').count(),int) else 0,
"digitales_count": ResourceInstance.objects.filter(graph_id='6afc4e9e-727e-4152-8084-309267752650').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='6afc4e9e-727e-4152-8084-309267752650').count(),int) else 0,
"actividades_count": ResourceInstance.objects.filter(graph_id='2bf240e6-718e-44f0-8073-4962d84931fe').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='2bf240e6-718e-44f0-8073-4962d84931fe').count(),int) else 0
}
return JsonResponse(data)
def post(self, request):
state = {
"b_muebles": ResourceInstance.objects.filter(graph_id='10b03fec-4d85-11ee-a708-ffcd06c08a5d').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='10b03fec-4d85-11ee-a708-ffcd06c08a5d').count(),int) else 0,
"b_inmuebles": ResourceInstance.objects.filter(graph_id='8ea3bf67-89ce-474c-b3cb-6dd5ee3d6198').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='8ea3bf67-89ce-474c-b3cb-6dd5ee3d6198').count(),int) else 0,
"inmaterial": ResourceInstance.objects.filter(graph_id='9b0e22c7-5c56-4be6-aa89-ae2632ba28e8').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='9b0e22c7-5c56-4be6-aa89-ae2632ba28e8').count(),int) else 0,
"sitios_arq": ResourceInstance.objects.filter(graph_id='76331d8a-4d85-11ee-a708-ffcd06c08a5d').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='76331d8a-4d85-11ee-a708-ffcd06c08a5d').count(),int) else 0,
"actores": ResourceInstance.objects.filter(graph_id='72420da0-db59-4048-aea2-03b0bc5cdcdf').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='72420da0-db59-4048-aea2-03b0bc5cdcdf').count(),int) else 0,
"digitales": ResourceInstance.objects.filter(graph_id='6afc4e9e-727e-4152-8084-309267752650').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='6afc4e9e-727e-4152-8084-309267752650').count(),int) else 0,
"actividades": ResourceInstance.objects.filter(graph_id='2bf240e6-718e-44f0-8073-4962d84931fe').count() if \
isinstance(ResourceInstance.objects.filter(graph_id='2bf240e6-718e-44f0-8073-4962d84931fe').count(),int) else 0
}
record = SystemRecord()
record.state_details = state
record.save()
data = {"records": self.serialize_system_records()}
return JsonResponse(data)