Skip to content

Commit

Permalink
v1.0.0rc1 la función habilitar y autoing pueden ser funciones
Browse files Browse the repository at this point in the history
(no solo strings de una tabla)
  • Loading branch information
emilioplatzer committed Mar 13, 2022
1 parent e299baa commit 154dd96
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 74 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -3,7 +3,7 @@ Validator de registros provenientes de formularios

Especialmente diseñado para encuestas

![extending](https://img.shields.io/badge/stability-extending-orange.svg)
![stable](https://img.shields.io/badge/stability-stable-green.svg)
[![npm-version](https://img.shields.io/npm/v/row-validator.svg)](https://npmjs.org/package/row-validator)
[![downloads](https://img.shields.io/npm/dm/row-validator.svg)](https://npmjs.org/package/row-validator)
[![build](https://github.com/codenautas/row-validator/actions/workflows/node.js.yml/badge.svg)](https://github.com/codenautas/row-validator/actions/workflows/node.js.yml)
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "row-validator",
"description": "Validator for rows of surveys",
"version": "0.7.4",
"version": "1.0.0-rc1",
"author": "Codenautas <codenautas@googlegroups.com>",
"license": "MIT",
"files": [
Expand Down
89 changes: 46 additions & 43 deletions src/lib/row-validator.ts
@@ -1,37 +1,35 @@
"use strict";

export type Valor = string | number | boolean | null

export interface Opcion<V>{
salto?:V|null // Destino del salto para la opción seleccionada
}

export interface Variable<V, FH, FIN>{
export type RowData<V extends string, D> = Record<V, D>

export type FuncionHabilitar<V extends string, D> = (formData: RowData<V, D>) => boolean
export type FuncionValoradora<V extends string, D> = (formData: RowData<V, D>) => D | null

export interface Variable<V extends string, D, FIN>{
optativa?:boolean // Obligatoriedad el ingreso de la variable
salto?:V|FIN|null // Destino del salto en caso de saltos icondicionales
tipo:'opciones'|'numerico'|'texto'|string
opciones?:{[k in string|number]:Opcion<V|FIN>}
opciones?:Record<string|number, Opcion<V|FIN>>
maximo?:number|null // Máximo valor válido
minimo?:number|null // Míximo valor válido
// Para variables de especifique dependientes de una opción:
subordinadaVar?:V|null // variable de la que depende
subordinadaValor?:Valor|null // valor que la activa
subordinadaValor?:D|null // valor que la activa
saltoNsNr?:V|FIN|null // Salto en el caso de no respuesta o NS/NC
calculada?:boolean|null // Si la variable es calculada (no ingresada)
funcionHabilitar?:FH|null // Determina la habilitación dinámica
funcionHabilitar?:FuncionHabilitar<V,D>|string|null // Determina la habilitación dinámica
libre?:boolean|null // Posibilidad de ingresarla aunque esté salteada
funcionAutoIngresar?:FH|null // Determina un cálculo para el valor inicial de una variable que se muestra al ser actual
funcionAutoIngresar?:FuncionValoradora<V,D>|string|null // Determina un cálculo para el valor inicial de una variable que se muestra al ser actual
}

export interface Structure<V extends string, FIN = true, FH extends string = string>{
variables:{
[k in V]:Variable<V, FH, FIN>
}
export interface Structure<V extends string, D, FIN = true>{
variables:Record<V, Variable<V, D, FIN>>
marcaFin?:FIN
}
export type RowData<V extends string> = {
[k in V]: any
}

export type EstadoVariableNormales = 'actual'|'valida'|'todavia_no'|'calculada'|'salteada'|'optativa_sd'
export type EstadoVariableErroneas = 'invalida'|'omitida'|'fuera_de_rango'|'fuera_de_flujo_por_omitida'|'fuera_de_flujo_por_salto'
Expand All @@ -47,31 +45,31 @@ export type Feedback<V extends string, FIN>={
pendiente:boolean|null
}

export type FormStructureState<V extends string, FIN> = {
export type FormStructureState<V extends string, D, FIN> = {
resumen:'vacio'|'con problemas'|'incompleto'|'ok'
feedbackResumen:Omit<Feedback<V,FIN>,'siguiente'|'apagada'|'inhabilitada'>
feedback:{[key in V]:Feedback<V,FIN>}
estados:{[key in V]?:EstadoVariable}
siguientes:{[key in V]?:V|FIN|null}
feedback:Record<V, Feedback<V,FIN>>
estados:Partial<Record<V, EstadoVariable>>
siguientes:Partial<Record<V, V|FIN|null>>
actual:V|null
primeraVacia?:V|null
primeraFalla:V|null
autoIngresadas?:Partial<{[v in V]: any}>
autoIngresadas?:Partial<RowData<V,D>>
};

export interface RowValidatorSetup {
getFuncionHabilitar:(name:string)=>((formData:RowData<string>)=>boolean)
getFuncionValorar: (name: string) => ((formData: RowData<string>) => any | null)
nsnrTipicos:{[k:string]: any}
export interface RowValidatorSetup<V extends string, D>{ // TODO PARAMETRIZR LOS TIPOS
getFuncionHabilitar: (name:string) => FuncionHabilitar<V, D>
getFuncionValorar: (name:string) => FuncionValoradora<V, D>
nsnrTipicos:Record<string, boolean>
multiEstado:boolean|null
}

export type OpcionesRowValidator={
autoIngreso?: boolean
}

export function getRowValidator(_setup:Partial<RowValidatorSetup>){
var setup:RowValidatorSetup={
export function getRowValidator<V extends string, D, FIN>(_setup:Partial<RowValidatorSetup<V, D>>){
var setup:RowValidatorSetup<V, D>={
getFuncionHabilitar:(nombre:string)=>{
throw new Error('rowValidator error. No existe la funcion habilitadora '+nombre);
},
Expand All @@ -85,9 +83,15 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
multiEstado:null,
..._setup
};
return function rowValidator<V extends string, FIN>(estructura:Structure<V, FIN>, formData:RowData<V>, opts?:OpcionesRowValidator){
var rta:FormStructureState<V, FIN>={
feedback:{} as FormStructureState<V, FIN>['feedback'],
return function rowValidator(estructura:Structure<V, D, FIN>, formData:RowData<V, D>, opts?:OpcionesRowValidator){
let getFuncionHabilitar = (nameOrFun: null | undefined | string | FuncionHabilitar<V,D>) =>
nameOrFun == null ? ()=>true :
nameOrFun instanceof Function ? nameOrFun : setup.getFuncionHabilitar(nameOrFun);
let getFuncionValorar = (nameOrFun: null | undefined | string | FuncionValoradora<V,D>) =>
nameOrFun == null ? ()=>null :
nameOrFun instanceof Function ? nameOrFun : setup.getFuncionValorar(nameOrFun);
var rta:FormStructureState<V, D, FIN>={
feedback:{} as FormStructureState<V, D, FIN>['feedback'],
feedbackResumen:{} as Feedback<V,FIN>,
estados:{},
siguientes:{},
Expand Down Expand Up @@ -155,8 +159,7 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
&& formData[estructuraVar.subordinadaVar]!=estructuraVar.subordinadaValor
|| /* caso 2*/
estructuraVar.tipo != 'filtro'
&& estructuraVar.funcionHabilitar
&& !setup.getFuncionHabilitar!(estructuraVar.funcionHabilitar)(formData)
&& !getFuncionHabilitar(estructuraVar.funcionHabilitar)(formData)
){ // la variable está inhabilitada ya sea por:
// 1) está subordinada y no es el valor que la activa
// 2) la expresión habilitar falla
Expand All @@ -177,7 +180,7 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
feedback.estado='todavia_no';
}else{
// hay que calcular si el filtro salta
let habilitado = estructuraVar.funcionHabilitar != null && setup.getFuncionHabilitar!(estructuraVar.funcionHabilitar)(formData)
let habilitado = getFuncionHabilitar(estructuraVar.funcionHabilitar)(formData)
if(habilitado){
feedback.estado='valida';
}else{
Expand All @@ -190,8 +193,8 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
if(!rta.primeraVacia){
rta.primeraVacia=miVariable;
}
if(opts && opts.autoIngreso && estructuraVar.funcionAutoIngresar){
let nuevoValor = setup.getFuncionValorar!(estructuraVar.funcionAutoIngresar)(formData);
if(opts && opts.autoIngreso){
let nuevoValor = getFuncionValorar(estructuraVar.funcionAutoIngresar)(formData);
if(nuevoValor != null){
rta.autoIngresadas![miVariable] = nuevoValor;
}
Expand All @@ -215,7 +218,7 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
libres++;
}
// hay algo ingresado hay que validarlo
if(setup.nsnrTipicos[valor]){
if(setup.nsnrTipicos[valor as unknown as string]){
feedback.estado='valida';
if(estructuraVar.saltoNsNr){
enSaltoAVariable=estructuraVar.saltoNsNr;
Expand All @@ -226,20 +229,22 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
if(estructuraVar.opciones==null){
throw new Error('rowValidator error. Variable "'+miVariable+'" sin opciones')
}
if(estructuraVar.opciones[valor]){
if(estructuraVar.opciones[valor as unknown as string]){
feedback.estado='valida';
feedback.pendiente=false;
if(estructuraVar.opciones[valor].salto){
enSaltoAVariable=estructuraVar.opciones[valor].salto;
if(estructuraVar.opciones[valor as unknown as string].salto){
enSaltoAVariable=estructuraVar.opciones[valor as unknown as string].salto;
variableOrigenSalto = miVariable;
}
}else{
falla('invalida');
}
}else if(estructuraVar.tipo=='numerico'){
valor=Number(valor);
if(estructuraVar.maximo !=null && valor > estructuraVar.maximo
|| estructuraVar.minimo != null && valor < estructuraVar.minimo){
var valorNumerico = Number(valor)
// @ts-expect-error No hay manera (por ahora) de que sepa que este valor en particular es un número
valor=valorNumerico
if(estructuraVar.maximo !=null && valorNumerico > estructuraVar.maximo
|| estructuraVar.minimo != null && valorNumerico < estructuraVar.minimo){
falla('fuera_de_rango');
}else{
feedback.estado='valida';
Expand Down Expand Up @@ -276,9 +281,7 @@ export function getRowValidator(_setup:Partial<RowValidatorSetup>){
}else{
feedback.siguiente=null;
}
if(!feedback.inhabilitada && estructuraVar.funcionHabilitar
&& !setup.getFuncionHabilitar!(estructuraVar.funcionHabilitar)(formData)
){
if(!feedback.inhabilitada && !getFuncionHabilitar!(estructuraVar.funcionHabilitar)(formData)){
feedback.inhabilitada=true;
}
rta.feedback[miVariable]=feedback;
Expand Down

0 comments on commit 154dd96

Please sign in to comment.