informe de avance

parent e4ad8b2a
<button
<!--<button
(click)="openConfig.emit()"
class="config-panel-toggle"
color="primary"
mat-fab
type="button">
<mat-icon svgIcon="mat:settings"></mat-icon>
</button>
</button>-->
<div
<div *ngIf="authService.isUiEnabled">
<div
[class.boxed]="isBoxed$ | async"
[class.horizontal-layout]="(isLayoutVertical$ | async) === false"
[class.is-mobile]="(isDesktop$ | async) === false"
......@@ -51,4 +52,5 @@
<ng-container *ngTemplateOutlet="footerRef"></ng-container>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
</div>
</div>
......@@ -17,6 +17,7 @@ import { filter, map, startWith, withLatestFrom } from 'rxjs/operators';
import { checkRouterChildsData } from '../utils/check-router-childs-data';
import { DOCUMENT } from '@angular/common';
import { ConfigService } from '../config/config.service';
import { AuthService } from 'src/app/core/auth/services/auth.service';
@UntilDestroy()
@Component({
......@@ -70,9 +71,9 @@ export class LayoutComponent implements OnInit, AfterViewInit {
searchOpen$ = this.layoutService.searchOpen$;
@ViewChild('quickpanel', { static: true }) quickpanel: MatSidenav;
@ViewChild('sidenav', { static: true }) sidenav: MatSidenav;
@ViewChild(MatSidenavContainer, { static: true })
@ViewChild('quickpanel', { static: false }) quickpanel: MatSidenav;
@ViewChild('sidenav', { static: false }) sidenav: MatSidenav;
@ViewChild(MatSidenavContainer, { static: false })
sidenavContainer: MatSidenavContainer;
constructor(
......@@ -81,6 +82,7 @@ export class LayoutComponent implements OnInit, AfterViewInit {
private layoutService: LayoutService,
private configService: ConfigService,
private router: Router,
public authService: AuthService,
@Inject(DOCUMENT) private document: Document
) {}
......@@ -100,16 +102,33 @@ export class LayoutComponent implements OnInit, AfterViewInit {
*/
this.layoutService.quickpanelOpen$
.pipe(untilDestroyed(this))
.subscribe(open =>
open ? this.quickpanel.open() : this.quickpanel.close()
);
.subscribe(open => {
try {
if (this.quickpanel) {
open ? this.quickpanel.open() : this.quickpanel.close();
}
} catch (error) {
console.log( error)
}
});
/**
* Open/Close Sidenav through LayoutService
*/
this.layoutService.sidenavOpen$
.pipe(untilDestroyed(this))
.subscribe(open => (open ? this.sidenav.open() : this.sidenav.close()));
.subscribe(open => {
try {
if (this.sidenav) {
open ? this.sidenav.open() : this.sidenav.close();
}
} catch (error) {
console.log( error)
}
});
/**
* Mobile only:
......
<button
<!--<button
#originRef
(click)="showPopover()"
[class.bg-hover]="dropdownOpen"
......@@ -7,3 +7,4 @@
type="button">
<mat-icon color="primary" svgIcon="mat:notifications_active"></mat-icon>
</button>
-->
<div class="flex items-center">
<!--<div class="flex items-center">
<button (click)="open()" mat-icon-button>
<mat-icon svgIcon="mat:search"></mat-icon>
</button>
......@@ -9,4 +9,4 @@
<mat-label>Search&hellip;</mat-label>
<input #input (blur)="close()" matInput />
</mat-form-field>
</div>
</div>-->
......@@ -36,9 +36,9 @@
<div class="-mx-1 flex items-center">
<div class="px-1">
<button (click)="openSearch()" mat-icon-button type="button">
<!-- <button (click)="openSearch()" mat-icon-button type="button">
<mat-icon color="primary" svgIcon="mat:search"></mat-icon>
</button>
</button> -->
</div>
<div class="px-1">
......@@ -46,15 +46,15 @@
</div>
<div class="px-1">
<button (click)="openQuickpanel()" mat-icon-button type="button">
<!-- <button (click)="openQuickpanel()" mat-icon-button type="button">
<mat-icon color="primary" svgIcon="mat:bookmarks"></mat-icon>
</button>
</button> -->
</div>
<div class="px-1">
<button [matMenuTriggerFor]="languageMenu" mat-icon-button type="button">
<!-- <button [matMenuTriggerFor]="languageMenu" mat-icon-button type="button">
<mat-icon svgIcon="flag:united-states"></mat-icon>
</button>
</button> -->
</div>
<div *ngIf="userVisible$ | async" class="px-1">
......
......@@ -12,6 +12,11 @@ import { Router } from '@angular/router';
providedIn: 'root',
})
export class AuthService {
public isUiEnabled: boolean = false;
private isVerifying: boolean = false;
private globalUserSubject: BehaviorSubject<GlobalUser> =
new BehaviorSubject<GlobalUser>(null);
globalUser$: Observable<GlobalUser> = this.globalUserSubject.asObservable();
......@@ -72,25 +77,25 @@ export class AuthService {
private getGlobalUser() {
const email = this.oAuthService.getIdentityClaims()['email'];
// Realizar la solicitud HTTP al backend para verificar si el email del usuario existe en tu tabla de usuarios
this.httpClient.get<boolean>(`http://localhost:8080/api/v1.0/users/by-email/${email}`).subscribe(
(exists: boolean) => {
this.isVerifying = false; // Restaurar la bandera de verificación
if (exists) {
//existe el email en la bdd
this.globalUserService
.getUserByUsername(this.tokenClaims.username)
.subscribe(user => {
// Existe el email en la bdd
this.globalUserService.getUserByUsername(this.tokenClaims.username).subscribe(user => {
this.setGlobalUser(user);
this.isUiEnabled = true; // Habilitar la interfaz una vez que se completa la verificación
});
}
},
(error) => {
this.isUiEnabled = false;
this.logout();
console.error('Error al verificar el email del usuario', error);
}
);
}
}
private setGlobalUser(user: GlobalUser) {
this.globalUserSubject.next(user);
......
export class actproy{
uzytavactproy_id?: number;
uzytavactproy_fech_regis?: Date;
uzytavactproy_observa?: string;
uzytavobjetivo_programa_id?: number;
uzytavproyec_id?: number;
}
export class detactproy{
uzytavdetactproy_id?: number;
uzytavactproy_id?: number;
uzytavobjetivo_programa_id?: number;
uzytavdetactproyporcent?: number;
uzytavdetactproyobserva?: string;
uzytavdetactproyresultado?: string;
}
......@@ -220,6 +220,10 @@ import { AporteUniEjecComponent } from './pages/Proyectos/Cierre/presupuesto eje
import { ErrorTextoComponent } from './pages/Proyectos/errores/error-texto/error-texto.component';
import { seguim } from './Models/hito';
import { ComisionAsigComponent } from './pages/asignar comision/comision-asig/comision-asig.component';
import { actproy } from './Models/actproy';
import { detactproy } from './Models/detactproy';
import { EditInformeBodyComponent } from './pages/Proyectos/Ejecución/informes de avance/edit-informe-body/edit-informe-body.component';
import { AddInformeComponent } from './pages/Proyectos/Ejecución/informes de avance/add-informe/add-informe.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [
......@@ -391,7 +395,9 @@ import { ComisionAsigComponent } from './pages/asignar comision/comision-asig/co
AporteEntEjecComponent,
AporteUniEjecComponent,
ErrorTextoComponent,
ComisionAsigComponent
ComisionAsigComponent,
EditInformeBodyComponent,
AddInformeComponent
],
imports: [
MatTreeModule,
......@@ -446,7 +452,9 @@ import { ComisionAsigComponent } from './pages/asignar comision/comision-asig/co
prograObj,
FormBuilder,
planvprograma,
programaeplanv
programaeplanv,
actproy,
detactproy
]
})
export class MainModule {
......
.area-busqueda {
padding: 20px;
margin-top: 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
.contenedorP {
width: 96%;
margin-left: 2%;
margin-right: 2%;
margin: 5px auto;
border-radius: 10px;
text-align: center;
margin-top: 2%;
background-color: white;
}
.mat-mdc-radio-button ~ .mat-mdc-radio-button {
margin-left: 16px;
}
.mat-radio-button{
margin-right: 10px;
}
.form-container {
display: flex;
flex-direction: column;
align-items: center;
width: 80%;
}
.formulario {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: 96%;
margin: 0 auto;
background-color: white;
padding: 10px;
border-radius: 10px;
}
.contenedor-dos {
margin-top: 30px;
padding: 0.9375rem 20px;
position: relative;
}
.form-field {
width: 100%;
margin-bottom: 20px;
}
.separator {
margin: 0 5px;
opacity: 0;
pointer-events: none;
}
.separator2 {
margin: 5px 0;
opacity: 0;
pointer-events: none;
}
<div class="contenedorP">
<div>
<form [formGroup]="myForm" (ngSubmit)="onUpdate()">
<mat-label *ngIf="ocultar"><strong>Seleccione una Actividad</strong></mat-label>
<mat-form-field class="form-field" *ngIf="ocultar">
<mat-label>Seleccione un Item</mat-label>
<mat-select formControlName="Actividades">
<mat-option *ngFor="let item of objetivosE"
[value]="item.uzytavobjetivo_programa_id">
{{ item.uzytavobjetivo_programaobjetivo_proy}}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</div>
</div>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddInformeComponent } from './add-informe.component';
describe('AddInformeComponent', () => {
let component: AddInformeComponent;
let fixture: ComponentFixture<AddInformeComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AddInformeComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(AddInformeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { objetivoprograma } from 'src/app/modules/main/Models/objetivoPrograma';
import { Actualiza_datosService } from 'src/app/modules/main/services/actualiza_datos/actualiza_datos.service';
import { Objetivo_programaService } from 'src/app/modules/main/services/objetivo_programa/objetivo_programa.service';
@Component({
selector: 'vex-add-informe',
templateUrl: './add-informe.component.html',
styleUrls: ['./add-informe.component.css']
})
export class AddInformeComponent implements OnInit {
myForm: FormGroup;
showData: boolean = false;
ShowDataAdd: boolean = false;
ocultar: boolean = true;
idRecuperado: number;
//arreglos
objetivosE: objetivoprograma[]=[];
constructor(
private objetS: Objetivo_programaService,
private datosCompartidos: Actualiza_datosService,
private formBuilder: FormBuilder
) {
this.myForm = this.formBuilder.group({
Actividades: ['', Validators.required]
});
}
ngOnInit(): void {
this.idRecuperado = parseInt(localStorage.getItem('proyectoId'),10);
this.datosCompartidos.datos$.subscribe(() => {
this.obtenerRegistros();
});
this.objetS.parametrosActualizados.subscribe(() => {
this.obtenerRegistros();
});
}
obtenerRegistros(){
this.objetS.registrosRelacionadosConProyecto(this.idRecuperado).subscribe(data =>{
this.objetivosE = data.filter( item => item.uzytavobjetivo_programatipo === 3);
console.log('impresión del arreglo', this.objetivosE)
});
}
AgregarF(){
}
cancelarF(){
}
onUpdate(){
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EditInformeBodyComponent } from './edit-informe-body.component';
describe('EditInformeBodyComponent', () => {
let component: EditInformeBodyComponent;
let fixture: ComponentFixture<EditInformeBodyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ EditInformeBodyComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(EditInformeBodyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'vex-edit-informe-body',
templateUrl: './edit-informe-body.component.html',
styleUrls: ['./edit-informe-body.component.css']
})
export class EditInformeBodyComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
<div class="container" #activitySection>
<vex-edit-informe *ngIf="idCompartido.mostrar4"></vex-edit-informe>
<vex-edit-informe-body *ngIf="idCompartido.mostrar5"></vex-edit-informe-body>
</div>
<div class="container">
<div class="div-container">
<label class="label-negrita"><strong>Listado de informes de avance</strong></label>
......@@ -15,8 +20,8 @@
</tr>
</thead>
<tbody>
<ng-container *ngFor="let item of objetivoEspe; let i = index">
<tr id="fila-{{i}}">
<ng-container *ngFor="let item of cabecera; let i = index">
<tr id="fila-{{i}}" >
<td>
<button (click)="toggleDiv(i)">
<mat-icon>{{ mostrarDiv[i] ? 'keyboard_arrow_down' :
......@@ -26,12 +31,16 @@
<td>
{{i+1}}
</td>
<td>{{item.uzytavobjetivo_programaobjetivo_proy}}</td>
<td>{{item.uzytavobjetivo_programaindicador_tipo}}</td>
<td>{{item.uzytavactproy_fech_regis}}</td>
<td>{{item.uzytavactproy_observa}}</td>
<td>
<button>
<mat-icon color="primary"
(click)="editarCabecera(item.uzytavactproy_id)">edit</mat-icon>
</button>
<button>
<mat-icon color="warn"
(click)="eliminar(item.uzytavobjetivo_programa_id)">delete</mat-icon>
(click)="eliminar(item.uzytavactproy_id)">delete</mat-icon>
</button>
</td>
</tr>
......@@ -46,24 +55,27 @@
<tr>
<th class="Column1 negrita">Nro</th>
<th class="Column1 negrita">Descripción</th>
<th class="Column1 negrita">Tipo Indicador</th>
<th class="Column1 negrita">Valor Indicador</th>
<th class="Column1 negrita">Descripción Indicador</th>
<th class="Column1 negrita">Medio de Verificación</th>
<th class="Column1 negrita">Supuestos</th>
<th class="Column1 negrita">Porcentaje</th>
<th class="Column1 negrita">Observación</th>
<th class="Column1 negrita">Resultados</th>
<th class="Column1 negrita">Editar</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let acti of objetivoEspe; let i = index">
<tr *ngFor="let acti of body; let i = index">
<ng-container
*ngIf="acti.uzytavobjetivo_programa_id_padre === item.uzytavobjetivo_programa_id">
*ngIf="acti.uzytavactproy_id === item.uzytavactproy_id">
<td>{{ i+1 }}</td>
<td>{{acti.uzytavobjetivo_programaobjetivo_proy}}</td>
<td>{{acti.uzytavobjetivo_programaindicador_tipo}}</td>
<td>{{acti.uzytavobjetivo_programaindicador_valor}}</td>
<td>{{acti.uzytavobjetivo_programaindicador}}</td>
<td>{{acti.uzytavobjetivo_programamverifica}}</td>
<td>{{acti.uzytavobjetivo_programasupuestos}}</td>
<td>{{getNombre(acti.uzytavobjetivo_programa_id)}}</td>
<td>{{acti.uzytavdetactproyporcent}}</td>
<td>{{acti.uzytavdetactproyobserva}}</td>
<td>{{acti.uzytavdetactproyresultado}}</td>
<td>
<button>
<mat-icon color="primary"
(click)="editarBody(acti.uzytavdetactproy_id)">edit</mat-icon>
</button>
</td>
</ng-container>
</tr>
</tbody>
......
import { Component, OnInit } from '@angular/core';
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { actproy } from 'src/app/modules/main/Models/actproy';
import { detactproy } from 'src/app/modules/main/Models/detactproy';
import { objetivoprograma } from 'src/app/modules/main/Models/objetivoPrograma';
import { Actualiza_datosService } from 'src/app/modules/main/services/actualiza_datos/actualiza_datos.service';
import { Compartir_idService } from 'src/app/modules/main/services/compartir_id/compartir_id.service';
import { Informes_avanceService } from 'src/app/modules/main/services/informes_avance/informes_avance.service';
import { MostrarOcultarService } from 'src/app/modules/main/services/mostrar-ocultar.service';
import { Objetivo_programaService } from 'src/app/modules/main/services/objetivo_programa/objetivo_programa.service';
@Component({
selector: 'vex-list-informe',
......@@ -7,17 +14,67 @@ import { objetivoprograma } from 'src/app/modules/main/Models/objetivoPrograma';
styleUrls: ['./list-informe.component.css']
})
export class ListInformeComponent implements OnInit {
@ViewChild('activitySection') activitySection!: ElementRef;
//para mostrar el div
mostrarDiv: boolean[] = [];
//objetivosEspe
objetivoEspe: objetivoprograma[] = [];
constructor() { }
//arreglos
cabecera: actproy[] = [];
body: detactproy[] = [];
public objetivo: objetivoprograma[] = [];
//variables
idRecuperado: number;
idObjetivo: number
constructor(
private informeS: Informes_avanceService,
private objetivoS: Objetivo_programaService,
private cabeceraM: actproy,
private bodyM: detactproy,
private compartirDatos: Actualiza_datosService,
private mostrarOcultarService: MostrarOcultarService,
public idCompartido: Compartir_idService
) { }
ngOnInit(): void {
this.idRecuperado = parseInt(localStorage.getItem('proyectoId'),10)
setTimeout(() => {
this.compartirDatos.datos$.subscribe(() =>{
this.obtenerRegistros();
});
this.informeS.parametrosActualizados.subscribe(() => {
this.obtenerRegistros();
});
});
}
//obtenerRegistros
obtenerRegistros(){
this.objetivoS.obtenerParametros().subscribe(data => {
this.objetivo = data;
});
this.informeS.obtenerCabecera().subscribe(dataCabecera => {
this.cabecera = dataCabecera.filter(item => item.uzytavproyec_id === this.idRecuperado);
});
this.informeS.obtenerCuerpo().subscribe(dataBody => {
this.body = dataBody;
});
}
//obtener el nombre
getNombre(id: number):string{
const busca = this.objetivo.find(i=> i.uzytavobjetivo_programa_id === id)
if(busca){
const nombre = busca.uzytavobjetivo_programaobjetivo_proy
return nombre;
}
return '';
}
//toggle div para desplegar
toggleDiv(i: number){
......@@ -26,6 +83,31 @@ export class ListInformeComponent implements OnInit {
//acciones para eliminar
eliminar(id: number){
console.log('registro eliminado',id)
}
editarCabecera(id: number){
this.idCompartido.mostrarFormulario4();
const registroSeleccionado = this.cabecera.find(
item => item.uzytavactproy_id === id
);
this.idCompartido.setCabe(id);
this.mostrarOcultarService.editCabecera = registroSeleccionado;
console.log('prueba para observar', id)
}
editarBody(id: number){
this.idCompartido.mostrarFormulario5();
const registroSeleccionado = this.body.find(
item => item.uzytavdetactproy_id === id
);
this.idCompartido.setCabe(id);
this.mostrarOcultarService.editBody = registroSeleccionado;
}
scrollIntoView() {
if (this.activitySection && this.activitySection.nativeElement) {
this.activitySection.nativeElement.scrollIntoView({ behavior: 'smooth' });
}
}
}
......@@ -543,7 +543,7 @@
1.- Informes de avance
</mat-panel-title>
</mat-expansion-panel-header>
<vex-edit-informe></vex-edit-informe>
<vex-add-informe></vex-add-informe>
<vex-list-informe></vex-list-informe>
<!--fin-->
</mat-expansion-panel>
......
......@@ -11,6 +11,8 @@ export class Compartir_idService {
private _mostrarFormulario: boolean = false;
private _mostrarFormulario2: boolean = false;
private _mostrarFormulario3: boolean = false;
private _mostrarFormulario4: boolean = false;
private _mostrarFormulario5: boolean = false;
private provincia: string;
private canton: string;
private parroquia: string;
......@@ -25,9 +27,32 @@ export class Compartir_idService {
private nombreDepartamento: string;
private idObje: number;
private id_insti: number;
private id_cabe:number;
private id_body: number;
constructor() { }
/*cabecera */
getCabe(){
return this.id_cabe
}
setCabe(id:number){
this.id_cabe = id;
}
/*body */
getBody(){
return this.id_body
}
setBody(id:number){
this.id_body = id;
}
getIdInst(){
return this.id_insti
}
......@@ -138,6 +163,30 @@ export class Compartir_idService {
return this._mostrarFormulario3;
}
mostrarFormulario4(): void {
this._mostrarFormulario4 = true;
}
ocultarFormulario4(): void {
this._mostrarFormulario4 = false;
}
get mostrar4(): boolean {
return this._mostrarFormulario4;
}
mostrarFormulario5(): void {
this._mostrarFormulario5 = true;
}
ocultarFormulario5(): void {
this._mostrarFormulario5 = false;
}
get mostrar5(): boolean {
return this._mostrarFormulario5;
}
setIdZonaDetalle(id: number) {
this.idZonaDetalle = id;
}
......
/* tslint:disable:no-unused-variable */
import { TestBed, async, inject } from '@angular/core/testing';
import { Informes_avanceService } from './informes_avance.service';
describe('Service: Informes_avance', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [Informes_avanceService]
});
});
it('should ...', inject([Informes_avanceService], (service: Informes_avanceService) => {
expect(service).toBeTruthy();
}));
});
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
import { Observable, Subject } from 'rxjs';
import { delay, tap } from 'rxjs/operators';
import { actproy } from '../../Models/actproy';
import { detactproy } from '../../Models/detactproy';
@Injectable({
providedIn: 'root'
})
export class Informes_avanceService {
parametrosActualizados: Subject<void> = new Subject<void>();
//URL cuerpo
private readonly URL1 = environment.appApiUrl + '/detactproy';
//Url Cabecera
private readonly URL2 = environment.appApiUrl + '/actproy';
//variables
private idGuardado: number;
constructor(private httpClient: HttpClient) { }
//Read
obtenerCabecera(): Observable<actproy[]> {
return this.httpClient.get<actproy[]>(`${this.URL2}/getAll`).pipe(delay(-1));
}
obtenerCuerpo():Observable<detactproy[]> {
return this.httpClient.get<detactproy[]>(`${this.URL1}/getAll`).pipe(delay(-1));
}
//create
guardarCabecera(parametros: actproy): Observable<any> {
return this.httpClient.post(`${this.URL2}/guardar`, parametros).pipe(
tap((response: any) => {
this.idGuardado = response.uzytavactproy_id;
})
);
}
obtenerIdCabe(): number {
return this.idGuardado;
}
//create body
guardarParametros(parametros: detactproy){
return this.httpClient.post(this.URL1 + '/guardar', parametros);
}
//eliminar cabecera
eliminarParametrosCabecera(id: number): Observable<any> {
return this.httpClient.delete(`${this.URL2}/eliminar/${id}`, { responseType: 'text' });
}
//eliminar body
eliminarParametrosBody(id: number): Observable<any> {
return this.httpClient.delete(`${this.URL1}/eliminar/${id}`, { responseType: 'text' });
}
//edit parametros
modificarParametrosCabecera(id: number, parametros: actproy): Observable<any> {
return this.httpClient.put<any>(`${this.URL2}/editar/${id}`, parametros);
}
modificarParametrosBody(id: number, parametros: detactproy): Observable<any> {
return this.httpClient.put<any>(`${this.URL2}/editar/${id}`, parametros);
}
}
......@@ -25,6 +25,8 @@ import { Parroquia } from '../Models/Ubicaciones/parroquia';
import { PresupuestoPartidas } from '../Models/presupuesto-partidas';
import { instproy } from '../Models/instproy';
import { objetivoprograma } from '../Models/objetivoPrograma';
import { actproy } from '../Models/actproy';
import { detactproy } from '../Models/detactproy';
@Injectable({
providedIn: 'root'
......@@ -59,5 +61,7 @@ export class MostrarOcultarService {
parroquiaEditado: Parroquia;
presupuestoEditado: PresupuestoPartidas;
editInst: instproy;
editObje: objetivoprograma
editObje: objetivoprograma;
editCabecera: actproy;
editBody: detactproy;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment