Compare commits

..

2 Commits

Author SHA1 Message Date
Juan Burgos
70460b3310 Adición del modo mapa satelital 2026-08-05 13:13:04 +00:00
Juan Burgos
e31ab73c05 Adición del modo mapa satelital 2026-08-05 13:12:42 +00:00
7 changed files with 109 additions and 32 deletions

View File

@@ -12,8 +12,10 @@ define([
//console.log('Params:', params); //console.log('Params:', params);
this.anexarUbic = ko.observable(false); this.anexarUbic = ko.observable(false);
this.satMap = ko.observable(false);
this.anexarImagenes = ko.observable(false); this.anexarImagenes = ko.observable(false);
this.anexarPdfs = ko.observable(false); this.anexarPdfs = ko.observable(false);
const boolToStr = (bool) => bool ? "1" : "0"; const boolToStr = (bool) => bool ? "1" : "0";
self.resourceId = ko.observable( self.resourceId = ko.observable(
@@ -23,7 +25,7 @@ define([
self.exportPDF = function() { self.exportPDF = function() {
var id = self.resourceId(); var id = self.resourceId();
if (id) { if (id) {
var url = '/export/pdf/' + id + '/' + boolToStr(self.anexarUbic()) + '/' + boolToStr(self.anexarImagenes()) + '/' + boolToStr(self.anexarPdfs()) + '/'; var url = '/export/pdf/' + id + '/' + boolToStr(self.anexarUbic()) + '/' + boolToStr(self.satMap()) + '/' + boolToStr(self.anexarImagenes()) + '/' + boolToStr(self.anexarPdfs()) + '/';
window.open(url, '_blank'); window.open(url, '_blank');
} else { } else {
alert('No se encontró el ID del recurso.'); alert('No se encontró el ID del recurso.');

View File

@@ -12,9 +12,61 @@ from zoneinfo import ZoneInfo
from functools import reduce from functools import reduce
from operator import getitem from operator import getitem
from pypdf import PdfReader, PdfWriter from pypdf import PdfReader, PdfWriter
import urllib.parse
import requests
import base64
import json import json
import ast import ast
def static_map_view(geojson_colec, sat_map):
geojson_dict = ast.literal_eval(geojson_colec)
if sat_map:
for geo in geojson_dict['features'] :
if geo['geometry'].get('type') == 'Polygon':
geo['properties'] = {
"stroke": "#00ffff",
"stroke-width": 2,
"stroke-opacity": 0.8,
"fill": "#00ffff",
"fill-opacity": 0.3
}
elif geo['geometry'].get('type') == 'Point':
geo['properties'] = {
"marker-color": "#ff0000",
"marker-size": "small"
}
elif geo['geometry'].get('type') == 'LineString':
geo['properties'] = {
"stroke": "#0000ff",
"stroke-width": 2,
"stroke-opacity": 0.8
}
geojson_string = json.dumps(geojson_dict, separators=(',', ':'))
encoded_geojson = urllib.parse.quote(geojson_string)
username = "mapbox"
if sat_map:
style_id = "satellite-streets-v12" # streets-v12 | outdoors-v11 | satellite-streets-v12
else:
style_id = "light-v11"
width, height = 340, 340
# Procedimiento pendiente para extraer el token desde la configuración del sistema
access_token = 'pk.eyJ1IjoianNidXJnb3N2IiwiYSI6ImNsaWhoN3ZtMTBxeHUzZm1xaGM0cGpxOXIifQ.ki3vldVB5MwZMqDSpLSjLg'
mapbox_url = (
f"https://api.mapbox.com/styles/v1/{username}/{style_id}/static/"
f"geojson({encoded_geojson})/auto/{width}x{height}"
f"?access_token={access_token}"
)
response = requests.get(mapbox_url)
return base64.b64encode(response.content).decode('utf-8')
def ajustar_medios(resource_media_rel, medios_list): def ajustar_medios(resource_media_rel, medios_list):
medios = [] medios = []
img=["image/bmp", "image/gif", "image/jpg", "image/jpeg", "image/png", "image/tif", "image/tiff"] img=["image/bmp", "image/gif", "image/jpg", "image/jpeg", "image/png", "image/tif", "image/tiff"]
@@ -83,12 +135,13 @@ def strdict_to_dict(strdict):
pass pass
return value return value
def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs): def export_resource_pdf(request, resourceid, printubic, satmap, printimgs, printpdfs):
resource = Resource.objects.get(pk=resourceid) resource = Resource.objects.get(pk=resourceid)
resource_data = resource.to_json() resource_data = resource.to_json()
# Corrección de medios relacionados, se normalizan claves y se adicionan propiedades # Corrección de medios relacionados, se normalizan claves y se adicionan propiedades
ruta_medios = find_key_path( resource_data, "Medio de información") ruta_medios = find_key_path( resource_data, "Medio de información")
if ruta_medios is not None: if ruta_medios is not None:
valor_medios=reduce(lambda dict_layer, key: dict_layer[key], ruta_medios, resource_data) valor_medios=reduce(lambda dict_layer, key: dict_layer[key], ruta_medios, resource_data)
resource_rel=resource.get_related_resources(user=request.user,resourceinstance_graphid='6afc4e9e-727e-4152-8084-309267752650') resource_rel=resource.get_related_resources(user=request.user,resourceinstance_graphid='6afc4e9e-727e-4152-8084-309267752650')
@@ -96,6 +149,7 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] = ajustar_medios(resource_rel,valor_medios) reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] = ajustar_medios(resource_rel,valor_medios)
# Cambio de datos gis en texto a formato json # Cambio de datos gis en texto a formato json
ruta_gis = find_key_path( resource_data, "Coordenadas / Geometría") ruta_gis = find_key_path( resource_data, "Coordenadas / Geometría")
if ruta_gis is not None: if ruta_gis is not None:
valor_gis=reduce(lambda dict_layer, key: dict_layer[key], ruta_gis, resource_data)["@value"] valor_gis=reduce(lambda dict_layer, key: dict_layer[key], ruta_gis, resource_data)["@value"]
@@ -111,7 +165,13 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
# Fecha del informe # Fecha del informe
sprpcb_url=request.build_absolute_uri('/')[:-1] sprpcb_url=request.build_absolute_uri('/')[:-1]
fecha=datetime.now(ZoneInfo("America/La_Paz")) fecha=datetime.now(ZoneInfo("America/La_Paz"))
map_img = None
if ruta_gis is not None and bool(int(printubic)) :
if reduce(getitem, ruta_gis[:-1], resource_data)[ruta_gis[-1]]["@value"] :
map_img = static_map_view(reduce(getitem, ruta_gis[:-1], resource_data)[ruta_gis[-1]]["@value"], bool(int(satmap)))
resources = [{ resources = [{
'resourceinstanceid': str(resource.resourceinstanceid), 'resourceinstanceid': str(resource.resourceinstanceid),
'graph_id': str(resource.graph_id), 'graph_id': str(resource.graph_id),
@@ -120,8 +180,10 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
'sprpcb_url': sprpcb_url, 'sprpcb_url': sprpcb_url,
'fecha': fecha, 'fecha': fecha,
'eta_group': eta_group, 'eta_group': eta_group,
'print_ubic': bool(int(printubic)),
'print_imgs': bool(int(printimgs)), 'print_imgs': bool(int(printimgs)),
'print_pdfs': bool(int(printpdfs)) 'print_pdfs': bool(int(printpdfs)),
'map_img': map_img
}] }]
context = {'resources': resources} context = {'resources': resources}
@@ -151,16 +213,18 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
root_path = Path(__file__).resolve().parent.parent root_path = Path(__file__).resolve().parent.parent
for medio in reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] : if ruta_medios is not None and bool(int(printpdfs)) :
if medio['formato'] == 'application/pdf' and bool(int(printpdfs)) : for medio in reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] :
merger.append(PdfReader(f'{root_path}/uploadedfiles/{medio["file"]}')) if medio['formato'] == 'application/pdf' :
output_buffer = io.BytesIO() merger.append(PdfReader(f'{root_path}/uploadedfiles/{medio["file"]}'))
merger.write(output_buffer) output_buffer = io.BytesIO()
merger.close() merger.write(output_buffer)
else: merger.close()
output_buffer = io.BytesIO() else:
merger.write(output_buffer) output_buffer = io.BytesIO()
merger.close() merger.write(output_buffer)
merger.close()
response = HttpResponse(output_buffer.getvalue(), content_type='application/pdf') response = HttpResponse(output_buffer.getvalue(), content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{nombre_pdf}.pdf"' response['Content-Disposition'] = f'attachment; filename="{nombre_pdf}.pdf"'
return response return response

View File

@@ -16,14 +16,15 @@
h3 { font-size: 12pt;} h3 { font-size: 12pt;}
h4 { font-size: 11pt;} h4 { font-size: 11pt;}
.tiles-grid-grp { display: grid; grid-template-columns: 3fr 2fr; grid-template-rows: auto auto; gap: 2px;} .tiles-grid-grp { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; gap: 2px;}
.tiles-grid-grp-col { grid-column: 2; grid-row: 1 / span 2; } .tiles-grid-grp-col { grid-column: 2; grid-row: 1 / span 2; }
.tile-block { border: 1px solid var(--ceniza); border-radius: 4px; padding: 2px; margin: 2px 0; background-color: var(--claro);} .tile-block { border: 1px solid var(--ceniza); border-radius: 4px; padding: 2px; margin: 2px 0; background-color: var(--claro);}
.tile-title { font-size: 11pt; font-weight: bold; color: var(--oscuro); border-bottom: 1px solid var(--ceniza); padding-bottom: 2px; margin-bottom: 5px;} .tile-title { font-size: 11pt; font-weight: bold; color: var(--oscuro); border-bottom: 1px solid var(--ceniza); padding-bottom: 2px; margin-bottom: 5px;}
.data-row { display: flex; padding: 2px 0; border-bottom: 1px solid var(--claro);} .data-row { display: flex; padding: 2px 0; border-bottom: 1px solid var(--claro);}
.data-label { font-weight: 600; letter-spacing: -0.05em; width: 40%; color: var(--oscuro);} .data-label { font-weight: 600; letter-spacing: -0.05em; width: 40%; color: var(--oscuro);}
.data-value { width: 40%; letter-spacing: -0.05em; word-wrap: break-word;} .data-value { width: 60%; font-size:.9em; word-wrap: break-word;}
.no-data { color: var(--ceniza); font-style: italic;} .no-data { color: var(--ceniza); font-style: italic;}
.tiles-grid-grp-col .tile-block img { object-fit: cover; width: 330px; max-height: 230px;}
@page { @page {
@top-left { background: var(--resaltado); content: counter(page); height: 1cm; text-align: center; width: 1cm;} @top-left { background: var(--resaltado); content: counter(page); height: 1cm; text-align: center; width: 1cm;}
@@ -117,7 +118,7 @@
{% with gis_vector=resource_data|val_from_key:"Ubicación simple"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %} {% with gis_vector=resource_data|val_from_key:"Ubicación simple"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
{% for gis in gis_vector.features %} {% for gis in gis_vector.features %}
<div class="data-row"> <div class="data-row">
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span> <span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
</div> </div>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
@@ -131,6 +132,7 @@
<div class="tiles-grid-grp-col"> <div class="tiles-grid-grp-col">
<div class="tile-block"> <div class="tile-block">
<div class="data-label">Mapa de referencia</div> <div class="data-label">Mapa de referencia</div>
<img src="data:image/png;base64,{{ resource.map_img }}">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -162,7 +162,7 @@
{% with gis_vector=resource_data|val_from_key:"Ubicación BIM"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %} {% with gis_vector=resource_data|val_from_key:"Ubicación BIM"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
{% for gis in gis_vector.features %} {% for gis in gis_vector.features %}
<div class="data-row"> <div class="data-row">
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span> <span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
</div> </div>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
@@ -175,6 +175,7 @@
<div class="tiles-grid-grp-col"> <div class="tiles-grid-grp-col">
<div class="tile-block"> <div class="tile-block">
<div class="tile-title">Mapa de referencia</div> <div class="tile-title">Mapa de referencia</div>
<img src="data:image/png;base64,{{ resource.map_img }}">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -152,15 +152,17 @@
<span class="data-label">Espacio: </span> <span class="data-label">Espacio: </span>
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Espacio" }}</span> <span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Espacio" }}</span>
</div> </div>
<div class="data-row"> {% if resource.print_ubic %}
<span class="data-label">Inmueble: </span> <div class="data-row">
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Inmueble" }}</span> <span class="data-label">Inmueble: </span>
</div> <span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Inmueble" }}</span>
<div class="data-row"> </div>
<span class="data-label">Colección: </span> <div class="data-row">
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Colección" }}</span> <span class="data-label">Colección: </span>
</div> <span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Colección" }}</span>
{% if resource_data|val_from_key:"Localización"|has_key:"Ubicación" %} </div>
{% endif %}
{% if resource_data|val_from_key:"Localización"|has_key:"Ubicación" and resource.print_ubic %}
<div class="data-row" style="margin-left: 15px;"> <div class="data-row" style="margin-left: 15px;">
<span class="data-value" style="width: 100%;"><b>Ambiente : </b> {{resource_data|val_from_key:"Localización"|val_from_key:"Ubicación"|val_from_key:"Ambiente" }}</span> <span class="data-value" style="width: 100%;"><b>Ambiente : </b> {{resource_data|val_from_key:"Localización"|val_from_key:"Ubicación"|val_from_key:"Ambiente" }}</span>
</div> </div>
@@ -180,11 +182,11 @@
<div class="data-row"> <div class="data-row">
<span class="data-label" style="width: 100%;">Coordenadas / Geometría: </span> <span class="data-label" style="width: 100%;">Coordenadas / Geometría: </span>
</div> </div>
{% if resource_data|val_from_key:"Localización"|has_key:"Coordenadas / Geometría" %} {% if resource_data|val_from_key:"Localización"|has_key:"Coordenadas / Geometría" and resource.print_ubic %}
{% with gis_vector=resource_data|val_from_key:"Localización"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %} {% with gis_vector=resource_data|val_from_key:"Localización"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
{% for gis in gis_vector.features %} {% for gis in gis_vector.features %}
<div class="data-row"> <div class="data-row">
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span> <span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
</div> </div>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
@@ -197,6 +199,7 @@
<div class="tiles-grid-grp-col"> <div class="tiles-grid-grp-col">
<div class="tile-block"> <div class="tile-block">
<div class="tile-title">Mapa de referencia</div> <div class="tile-title">Mapa de referencia</div>
<img src="data:image/png;base64,{{ resource.map_img }}">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -126,7 +126,7 @@
{% with gis_vector=resource_data|val_from_key:"Ubicación 2"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %} {% with gis_vector=resource_data|val_from_key:"Ubicación 2"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
{% for gis in gis_vector.features %} {% for gis in gis_vector.features %}
<div class="data-row"> <div class="data-row">
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span> <span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
</div> </div>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
@@ -140,6 +140,7 @@
<div class="tiles-grid-grp-col"> <div class="tiles-grid-grp-col">
<div class="tile-block"> <div class="tile-block">
<div class="tile-title">Mapa de referencia</div> <div class="tile-title">Mapa de referencia</div>
<img src="data:image/png;base64,{{ resource.map_img }}">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -15,11 +15,15 @@
</div> </div>
<div class="report-print-date" data-bind="component: { <div class="report-print-date" data-bind="component: {
name: 'views/components/simple-switch', name: 'views/components/simple-switch',
params: { value: anexarImagenes, config:{ label: 'Incluir imágenes adjuntas'}}}"> params: { value: satMap, config:{ label: 'Mapa satelital'}}}">
</div> </div>
<div class="report-print-date" data-bind="component: { <div class="report-print-date" data-bind="component: {
name: 'views/components/simple-switch', name: 'views/components/simple-switch',
params: { value: anexarPdfs, config:{ label: 'Incluir documentos (pdf) adjuntos'}}}"> params: { value: anexarImagenes, config:{ label: 'Adjuntar imágenes'}}}">
</div>
<div class="report-print-date" data-bind="component: {
name: 'views/components/simple-switch',
params: { value: anexarPdfs, config:{ label: 'Adjuntar documentos (pdf)'}}}">
</div> </div>
</div> </div>
</div> </div>