Fusion de cosas en licitaciones

This commit is contained in:
2025-07-30 09:14:11 +02:00
8 changed files with 626 additions and 16 deletions

View File

@@ -5,8 +5,10 @@
@using System.Text
@using bdHerramientaCACOA.db
@using Newtonsoft.Json
@using PuppeteerSharp
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedLocalStorage ProtectedLocalStore
@inject IJSRuntime JS
@rendermode InteractiveServer
@inject NavigationManager Navigation
@@ -47,6 +49,10 @@
<b class="Fuente2 ps-2 pe-2 nomSim">Nombre de la simulación: </b>
<InputText @bind-Value="casa.NombreSimulacion" class="form-control inputForm formatoMoneda inputTabla " style="text-align:left;font-weight:bold;"></InputText>
</div>
<Button @onclick="imprimir">Imprimir</Button>
<Tabs>
<Tab Title="Despacho Profesional" Name="tabDespachoProf" Active>
<Content>
@@ -64,7 +70,7 @@
</Tab>
<Tab Title="Costes de producción" Name="tabCosteProd">
<Content>
<div class="CajaTab p-2">
<div class="CajaTab p-2">
<HerramientaCASA.Components.Pages.HerramientaCASATabs.CostesProduccion objetoCASA="casa"></HerramientaCASA.Components.Pages.HerramientaCASATabs.CostesProduccion>
</div>
</Content>
@@ -72,7 +78,9 @@
</Tabs>
</div>
<div style="display:none">
<HerramientaCASA.Components.Pages.Imprimir.HerramientaCASAImprimir objetoCASA="casa"></HerramientaCASA.Components.Pages.Imprimir.HerramientaCASAImprimir>
</div>
@code {
[Parameter]
public string? idSimulador { get; set; } = "";
@@ -83,6 +91,7 @@
public bool actualizado = true;
string nombreOriginal = "";
private string pdfUrl;
public tsHerramientasCACOA bd;
public bdHerramientaCACOA.CASA casa = new CASA();
@@ -103,7 +112,7 @@
idSimulador = clValue;
}
if (string.IsNullOrEmpty(idSimulador))
{
@@ -267,4 +276,89 @@
{
await popupGuardar.HideAsync();
}
private async Task imprimir()
{
var cssPath = Path.Combine(Environment.CurrentDirectory, "wwwroot", "Content", "Site.css");
var cssContent = await File.ReadAllTextAsync(cssPath);
var contenidoHtml = await JS.InvokeAsync<string>("obtenerContenidoHtml");
var fullHtml = $@"
<html>
<head>
<style>{cssContent}</style>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css' rel='stylesheet' integrity='sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN' crossorigin='anonymous'>
</head>
<body>
{contenidoHtml}
</body>
</html>";
var fileName = $"factura_{DateTime.Now:yyyyMMddHHmmss}.pdf";
var filePath = Path.Combine("wwwroot", fileName);
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--ignore-certificate-errors" }
});
using var page = await browser.NewPageAsync();
await page.SetViewportAsync(new ViewPortOptions { Width = 1200, Height = 800 });
await page.SetContentAsync(fullHtml);
await page.PdfAsync(filePath, new PdfOptions
{
PrintBackground = true,
Format = PuppeteerSharp.Media.PaperFormat.A4,
MarginOptions = new PuppeteerSharp.Media.MarginOptions
{
Top = "20mm",
Bottom = "20mm"
}
});
pdfUrl = "/" + fileName;
Navigation.NavigateTo(pdfUrl, true);
}
}
<script>
function obtenerContenidoHtml() {
const DespachoImprimir = document.getElementById('DespachoImprimir');
// const contenido2 = document.getElementById('CosteExterna');
let html = DespachoImprimir.outerHTML + "<br>";
return html;
};
// async function obtenerTablasDeOtraPagina(url) {
// const response = await fetch(url);
// const texto = await response.text();
// const parser = new DOMParser();
// const doc = parser.parseFromString(texto, 'text/html');
// // Selecciona las dos primeras tablas
// const tablas = doc.querySelectorAll('table');
// const tabla1 = tablas[0]?.outerHTML || '';
// const tabla2 = tablas[1]?.outerHTML || '';
// return tabla1 + '<br><br>' + tabla2;
// }
</script>

View File

@@ -127,7 +127,7 @@
}
</div>
<div class="col-md-4" style="align-items: flex-end;">
<div class="col-md-4" style="align-items: flex-end;">
<div style="height: 49px;">
<b>Coste hora Despacho Profesional</b>
</div>
@@ -170,7 +170,7 @@
</div>
</div>
<div class="col-md-4">
<div class="col-md-4">
<div style="height: 49px;">
<b>Coste hora Externalización</b>
@@ -187,7 +187,7 @@
<tr>
<td class="colorFilasIntro w4">Incremento por externalización</td>
<td class="text-end">
<div class="d-flex" style="gap:3px">
<div id="numeroExterna" class="d-flex" style="gap:3px">
<InputNumber TValue="double" Locale="es-ES" Min="0" class="inputForm formatoMoneda inputTabla" Value="@objetoCASA.CostesProduccion.CoeficienteCostesExternalizacion" ValueExpression="() => objetoCASA.CostesProduccion.CoeficienteCostesExternalizacion" ValueChanged="(value) => CosteExtCambiado(value)"></InputNumber> %
</div>
</td>

View File

@@ -8,7 +8,6 @@
@using bdHerramientaCACOA.db
@inject NavigationManager Navigation
@inject UserState UserState
@inject IJSRuntime JS
<div>
@@ -17,9 +16,8 @@
</CascadingValue>
</div>
@* <Button @onclick="imprimir">Imprimir</Button> *@
<div class="container-fluid m-0 p-0">
<div class="container-fluid m-0 p-0">
<div class="row">
<div class="col-md-8 d-flex flex-column">
<div>
@@ -68,6 +66,7 @@
[Parameter]
public string? idSimulador { get; set; } = "";
private int idFicheroObtenido = 0;
public tsHerramientasCACOA bd;
@@ -110,6 +109,10 @@
}
// private void clonarDespacho()
// {
// var byteFichero = bd.ficheros.First(x=> x.idFichero == idFicheroObtenido).Fichero;
@@ -127,10 +130,3 @@
// }
}
@* <script>
function obtenerHtmlDespacho() {
const contenido = document.querySelector('.container-fluid');
return contenido ? contenido.outerHTML : "";
};
</script> *@

View File

@@ -0,0 +1,314 @@
<div id="DespachoImprimir" class="d-flex flex-column align-items-center">
<div class="col-12 mx-auto mb-5">
<div class="mb-4 col-8 mx-auto justify-content-center d-flex">
<label style="color: #078b98 !important"><b>Despacho Profesional</b></label>
</div>
<div class="col-8 mx-auto" style="align-items: flex-end;">
<div style="height: 49px;">
<b>Coste hora Despacho Profesional</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Tipo de costes</th>
<th class="colorB fw-bold">Coste/hora</th>
</tr>
</thead>
<tbody>
<tr>
<td class="colorB w4">Costes directos</td>
<td class="text-end">@objetoCASA.DespachoProfesional.CostesDirectos.MilesYDecimales() €/hora</td>
</tr>
<tr>
<td class="colorB ">Costes indirectos</td>
<td class="text-end">@objetoCASA.DespachoProfesional.TasaCostesIndirectos.MilesYDecimales() €/hora</td>
</tr>
<tr>
<td class="colorB ">Costes variables</td>
<td class="text-end">@objetoCASA.CostesProduccion.CostesVariables.MilesYDecimales() €/hora</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-end fw-bold colorC TotalesTabla">
<div style="height:28px; align-content:center;">
Total Coste hora Despacho Profesional: <span> @objetoCASA.CostesProduccion.TotalCostes.MilesYDecimales() €/hora</span>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="col-8 mx-auto">
<div style="height: 49px;">
<b>Coste hora Externalización</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Externalización</th>
<th class="colorB fw-bold">Porcentaje</th>
</tr>
</thead>
<tbody>
<tr>
<td class="colorFilasIntro w4">Incremento por externalización</td>
<td class="text-end">
<span>
@objetoCASA.CostesProduccion.CoeficienteCostesExternalizacion
</span>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-end fw-bold colorC TotalesTabla">
Coste hora Externalización: <span> @objetoCASA.CostesProduccion.CosteHoraExternalizacion.MilesYDecimales() €/hora</span>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="col-12 mx-auto mb-5">
<div class="mb-4 col-11 mx-auto justify-content-center d-flex">
<label style="color: #078b98 !important"><b>Trabajo Profesional</b></label>
</div>
@if (objetoCASA.TrabajoProfesional.Usos.Count != 0)
{
<div class="col-11 mx-auto" style="align-items: flex-end;">
<div style="height: 49px;">
<b>Usos/Tipologías</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Superficie</th>
<th class="colorB fw-bold">Usos</th>
<th class="colorB fw-bold">Tipología</th>
<th class="colorB fw-bold">Intervención</th>
</tr>
</thead>
<tbody>
@foreach(var uso in objetoCASA.TrabajoProfesional.Usos){
<tr>
<td class="text-end">@uso.superficie.MilesYDecimales()</td>
<td>@objetoCASA.Enumerados.GruposTipologias?.FirstOrDefault(x => x.idEnumeracion == uso.idGrupoTipologia)?.ValorAlfabetico1</td>
<td>@objetoCASA.Enumerados.Tipologias?.FirstOrDefault(x => x.idTipologia == uso.idTipologia)?.Descripcion</td>
<td>@objetoCASA.Enumerados.Intervenciones?.FirstOrDefault(x => x.idEnumeracion == uso.idTipoIntervencion)?.ValorAlfabetico1</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="4" class="text-end fw-bold colorC TotalesTabla">
<div style="height:28px; align-content:center;">
Total superficie: <span> @objetoCASA.TrabajoProfesional.Usos.Sum(x=>x.superficie).MilesYDecimales()</span>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
}
<div class="col-10 mx-auto" style="align-items: flex-end;">
<div class="d-flex justify-content-center">
<div class="col-md-10">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<tr>
<td class="colorFilasIntro fw-bold">Plazo de presentación de la documentación:</td>
<td class="text-end">
<span class="inputForm formatoMoneda text-end">@objetoCASA.CostesProduccion.PlazoPresentacionDocumentos</span>
</td>
</tr>
</table>
<div class="mb-3" style="height:20px;">
@if (objetoCASA.CostesProduccion.IncrementoUrgencia > 0)
{
<label style="font-size:10px;">Incremento del @objetoCASA.CostesProduccion.IncrementoUrgencia% en los costes de producción de la documentación por plazo de presentación reducido</label>
}
</div>
</div>
</div>
</div>
<div class="col-10 mx-auto d-flex justify-content-center" style="align-items: flex-end;">
<div class="col-md-10 row ">
<div style="height: 49px;">
<b>Trabajo profesional</b>
</div>
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold w-75">Trabajos</th>
<th class="colorB fw-bold ">Horas</th>
</tr>
</thead>
<tbody>
<tr>
<td class="colorB fw-bold">Horas elaboración documentación</td>
<td class="text-end">@objetoCASA.TrabajoProfesional.HorasTPEDocumentacion.MilesYDecimales() h</td>
</tr>
<tr>
<td class="colorB text-end">Horas de documentación en Despacho Profesional</td>
<td class="text-start">@objetoCASA.CostesProduccion.HorasProduccionDespachoElabDocumentacion.MilesYDecimales() h</td>
</tr>
<tr>
<td class="colorB text-end">Horas de documentación mediante externalización</td>
<td class="text-start">@objetoCASA.CostesProduccion.NumHorasMinimoExt.MilesYDecimales() h</td>
</tr>
<tr>
<td class="colorB fw-bold">Horas de dirección de obra</td>
<td class="text-end">@objetoCASA.TrabajoProfesional.HorasTPEDireccion.MilesYDecimales() h</td>
</tr>
<tr>
<td class="colorC fw-bold w4">HORAS TRABAJO PROFESIONAL</td>
<td class="text-end">@objetoCASA.TrabajoProfesional.HorasTPE.MilesYDecimales() h</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-12 mx-auto mb-5">
<div class="mb-4 col-8 mx-auto justify-content-center d-flex">
<label style="color: #078b98 !important"><b>Costes de Producción</b></label>
</div>
<div class="col-8 mx-auto">
<div style="height: 49px;">
<b>Costes Asociados a los Servicios de Arquitectura</b>
</div>
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold w-75">Concepto</th>
<th class="colorB fw-bold text-end"></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tdAlter fw-bold " style="background:#ffc107;">COSTES DE PRODUCCIÓN DEL TRABAJO PROFESIONAL</td>
<td class="text-end"><span> @objetoCASA.CostesProduccion.CostesProduccionTrabProf.MilesYDecimales() €</span></td>
</tr>
<tr>
<td class="colorFilasIntro w4"><b>Beneficio</b> (antes de impuestos)</td>
<td class="text-end">
<span class="inputForm formatoMoneda">@objetoCASA.CostesProduccion.Beneficio </span>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-end fw-bold">
Precio del trabajo profesional: <span>@objetoCASA.CostesProduccion.PrecioTrabProf.MilesYDecimales() € </span>
</td>
</tr>
</tfoot>
</table>
</div>
@if (objetoCASA.CostesProduccion.OtrosTrabajos.Count != 0)
{
<div class="col-8 mx-auto">
<div style="height: 49px;">
<b>Otros trabajos incluidos en el Encargo</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Encargo</th>
<th class="colorB fw-bold">Precio</th>
</tr>
</thead>
<tbody>
@foreach (var otroTrabajo in objetoCASA.CostesProduccion.OtrosTrabajos)
{
<tr>
<td>@otroTrabajo.Denominacion</td>
<td class="text-end">@otroTrabajo.Coste.MilesYDecimales()</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-end fw-bold colorC TotalesTabla">
<div class="d-flex justify-content-end">
<div style="align-self: center;">
Total Otros trabajos:
<span> @objetoCASA.CostesProduccion.TotalOtrosTrabajos.MilesYDecimales() €</span>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2" class="text-end fw-bold TotalesTabla" style="background: #ffc107;">
Precio del encargo: <span>@objetoCASA.CostesProduccion.PrecioDelEncargo.MilesYDecimales() € </span>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
}
</div>
</div>
@code {
[Parameter]
public bdHerramientaCACOA.CASA objetoCASA { get; set; } = new bdHerramientaCACOA.CASA();
public tsHerramientasCACOA bd;
protected override async Task OnInitializedAsync()
{
bd = tsHerramientasCACOA.NuevoContexto(SoloLectura: false);
}
public void RefreshState()
{
this.StateHasChanged();
}
}

View File

@@ -0,0 +1,133 @@
<div id="LicitacionesCASAImprimir" class="d-flex flex-column align-items-center">
<div class="col-12 mx-auto mb-5">
<div class="mb-4 col-11 mx-auto justify-content-center d-flex">
<label style="color: #078b98 !important"><b>Licitaciones Edificación</b></label>
</div>
<div class="col-11 mx-auto" style="align-items: flex-end;">
<div style="height: 49px;">
<b>Usos/Tipologías</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Superficie</th>
<th class="colorB fw-bold">Usos</th>
<th class="colorB fw-bold">Tipología</th>
<th class="colorB fw-bold">Intervención</th>
</tr>
</thead>
<tbody>
@foreach (var uso in objetoLicitaciones.Usos)
{
<tr>
<td class="text-end">@uso.superficie.MilesYDecimales()</td>
<td>@objetoLicitaciones.Enumerados.GruposTipologias?.FirstOrDefault(x => x.idEnumeracion == uso.idGrupoTipologia)?.ValorAlfabetico1</td>
<td>@objetoLicitaciones.Enumerados.Tipologias?.FirstOrDefault(x => x.idTipologia == uso.idTipologia)?.Descripcion</td>
<td>@objetoLicitaciones.Enumerados.Intervenciones?.FirstOrDefault(x => x.idEnumeracion == uso.idTipoIntervencion)?.ValorAlfabetico1</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="4" class="text-end fw-bold colorC TotalesTabla">
<div style="height:28px; align-content:center;">
Total superficie: <span> @objetoLicitaciones.Usos.Sum(x => x.superficie).MilesYDecimales()</span>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="col-11 mx-auto" style="align-items: flex-end;">
<div style="height: 49px;">
<b>Fases</b>
</div>
<div class="table-responsive">
<table class="table tablaCACOA tablaCACOA2 mb-0">
<thead>
<tr>
<th class="colorB fw-bold">Fases</th>
<th class="colorB fw-bold"></th>
</tr>
</thead>
<tbody>
@foreach (var fase in objetoLicitaciones.FasesTrabajo)
{
<tr>
<td >@fase.Denominacion</td>
<td class="text-end">
<div style="gap:3px;">
<span>@fase.Porcentaje</span>
@if (fase.Seleccionado)
{
<span> poner tick </span>
}
</div>
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-end fw-bold colorC TotalesTabla">
<div class="d-flex justify-content-end">
<div style="align-self: center;">
@if (objetoLicitaciones.FasesTrabajo
.Where(f => f.Seleccionado)
.Sum(f => f.Porcentaje) != 100)
{
<div>
Trabajo en misión parcial: <span>
@objetoLicitaciones.FasesTrabajo.Where(f => f.Seleccionado).Sum(f => f.Porcentaje) %
</span>
</div>
}
else
{
<div>
Total: <span>
@objetoLicitaciones.FasesTrabajo.Where(f => f.Seleccionado).Sum(f => f.Porcentaje) %
</span>
</div>
}
</div>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
@code {
[Parameter]
public LICITACIONES objetoLicitaciones { get; set; } = new LICITACIONES();
public tsHerramientasCACOA bd;
protected override async Task OnInitializedAsync()
{
bd = tsHerramientasCACOA.NuevoContexto(SoloLectura: false);
}
public void RefreshState()
{
this.StateHasChanged();
}
}

View File

@@ -4,8 +4,10 @@
@using Microsoft.EntityFrameworkCore
@using bdHerramientaCACOA.db
@using HerramientaCASA.Components.Pages.LicitacionesGrids
@using PuppeteerSharp
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedLocalStorage ProtectedLocalStore
@inject IJSRuntime JS
@page "/LicitacionCASA"
@page "/LicitacionCASA/{idSimulador}"
@@ -51,6 +53,8 @@
<InputText @bind-Value="objetoLicitaciones.Descripcion" class="form-control inputForm formatoMoneda inputTabla " style="text-align:left;font-weight:bold;"></InputText>
</div>
<Button @onclick="imprimir">Imprimir</Button>
<div class="row">
<div class="col-md-6 mt-3 mb-2">
<div><b>Convenio Colectivo:</b></div>
@@ -111,6 +115,9 @@
</div>
</div>
</div>
<div style="display:none">
<HerramientaCASA.Components.Pages.Imprimir.LicitacionesCASAImprimir objetoLicitaciones="objetoLicitaciones"></HerramientaCASA.Components.Pages.Imprimir.LicitacionesCASAImprimir>
</div>
@* <div class="row">
<div class="col-md-12">
<table class="tablaAlter mt-3 mb-3">
@@ -205,6 +212,8 @@
private bdHerramientaCACOA.LICITACIONES objetoLicitaciones;
private string pdfUrl;
private int idUser = 0;
public bool modificarTabla = true;
@@ -384,6 +393,57 @@
{
await popupGuardar.HideAsync();
}
private async Task imprimir()
{
var cssPath = Path.Combine(Environment.CurrentDirectory, "wwwroot", "Content", "Site.css");
var cssContent = await File.ReadAllTextAsync(cssPath);
var contenidoHtml = await JS.InvokeAsync<string>("obtenerContenidoHtml");
var fullHtml = $@"
<html>
<head>
<style>{cssContent}</style>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css' rel='stylesheet' integrity='sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN' crossorigin='anonymous'>
</head>
<body>
{contenidoHtml}
</body>
</html>";
var fileName = $"factura_{DateTime.Now:yyyyMMddHHmmss}.pdf";
var filePath = Path.Combine("wwwroot", fileName);
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--ignore-certificate-errors" }
});
using var page = await browser.NewPageAsync();
await page.SetViewportAsync(new ViewPortOptions { Width = 1200, Height = 800 });
await page.SetContentAsync(fullHtml);
await page.PdfAsync(filePath, new PdfOptions
{
PrintBackground = true,
Format = PuppeteerSharp.Media.PaperFormat.A4,
MarginOptions = new PuppeteerSharp.Media.MarginOptions
{
Top = "20mm",
Bottom = "20mm"
}
});
pdfUrl = "/" + fileName;
Navigation.NavigateTo(pdfUrl, true);
}
private async void modificarTablaChanged(bool res)
@@ -419,3 +479,15 @@
}
}
<script>
function obtenerContenidoHtml() {
const LicitacionImprimir = document.getElementById('LicitacionesCASAImprimir');
let html = LicitacionImprimir.outerHTML;
return html;
};
</script>

View File

@@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Blazor.Bootstrap" Version="3.3.1" />
<PackageReference Include="PuppeteerSharp" Version="20.2.2" />
</ItemGroup>
<ItemGroup>

Binary file not shown.