Recetas de scripts
Patrones de script listos para adaptar, extraídos del comportamiento real de las secciones del núcleo Ready-To-Go de Dinaup.
Cada receta resuelve una necesidad concreta con un script real: son los mismos patrones que ejecutan las secciones del núcleo de Dinaup (Ventas, Tareas de Proyectos, líneas de factura…), adaptados para que los copies y cambies los campos por los tuyos. Los conceptos (eventos, ámbitos, tipos) están en Scripts y eventos; la sintaxis de C. en el registro del formulario.
Un detalle que verás repetido: salir corta la ejecución del script en ese punto. Es la guarda habitual para salir pronto cuando el script no aplica.
Rellenar valores por defecto al iniciar un alta
Evento: Formulario para agregar iniciado — se dispara al abrir el formulario de un registro nuevo, antes de que el usuario escriba.
@ La clave definitiva la asigna el servidor al guardar
C.Clave = 'DRAFT'
F.Field_SetFocus(S.Fields.TareasDeProyectos.Resumen.ID, 0)
@ La tarea hereda el tipo inicial definido en el flujo del proyecto
C.ReferenciaTipo = F.GetRowById(S.Sections.TiposDeTareaDeProyectos.ID, C.ReferenciaProyecto.ReferenciaFlujo.ReferenciaTipo)
@ Y el bono de horas del proyecto, si no trae uno
if C.ReferenciaBono = ''
C.ReferenciaBono = F.GetRowById(S.Sections.BonosHoras.ID, C.ReferenciaProyecto.ReferenciaBono)
C.ImporteBonoPrecioHorasinImpuestos = C.ReferenciaProyecto.ImporteBonoPrecioHorasinImpuestos
end ifAsí arranca una tarea de Proyectos: foco en el campo que toca escribir primero y los campos heredados del proyecto ya puestos.
Autorrellenar campos al elegir una relación
Evento: Campo cambiado, sobre el campo de relación. Al seleccionar el cliente, la venta copia sus condiciones y calcula el vencimiento.
txt condicionesDePago = C.ReferenciaCliente.CondicionesPagoVenta
num condicionesDePagoDias = C.ReferenciaCliente.PlazoDiasCobroVentas
if v.condicionesDePago <> ''
C.CondicionesDePago = v.condicionesDePago
end if
if v.condicionesDePagoDias <> 0 or v.condicionesDePago <> ''
C.FechaDeVencimiento = F.Date_AddDays(D.DatosEspeciales.FechaActual, v.condicionesDePagoDias)
end ifEl script lee la ficha del cliente a través de la relación y solo pisa los campos cuando la ficha aporta valor. El autorrellenado declarativo cubre el caso simple (copiar campo a campo); el script entra cuando hay condiciones o cálculo por medio.
Derivar campos cuando cambia el estado
Evento: Campo cambiado, sobre el campo de estado. El registro mantiene solos sus indicadores y fechas reales.
if C.ReferenciaEstado.EstadoTarea = S.Enums.tareaestado.enproceso
C.EnProceso = 1
¿C.FechaInicioConfirmado = '' ? C.FechaInicioConfirmado = D.DatosEspeciales.FechaActual
else
C.EnProceso = 0
end if
@ Volver al backlog borra la fecha de inicio real
if C.ReferenciaEstado.EstadoTarea = S.Enums.tareaestado.backlog or C.ReferenciaEstado.EstadoTarea = S.Enums.tareaestado.pendiente
C.FechaInicioConfirmado = ''
end if
¿C.ReferenciaEstado.EstadoTarea = S.Enums.tareaestado.completado ? C.ProgresoPorciento = 100La comparación no es contra el nombre del estado, sino contra el enum de su ficha: el usuario puede renombrar estados sin romper el script.
Bloquear el guardado si algo no cuadra
Evento: Antes de aceptar. Es el último control antes de que el registro se guarde: si la validación falla, F.CancelEvent() lo impide.
if C.ReferenciaDepartamento <> '' and C.ReferenciaSubdepartamento <> ''
if C.ReferenciaSubdepartamento.ReferenciaDepartamentoQuePertenece <> C.ReferenciaDepartamento
F.MsgBox('El subdepartamento seleccionado no pertenece al departamento.', 1)
F.CancelEvent()
end if
end ifEl mensaje dice qué está mal y el guardado no ocurre. El segundo parámetro de F.MsgBox es la acción en emulación REST, para cuando el script lo dispara una escritura por API en vez de un usuario; ver funciones de interacción.
Pedir confirmación en vez de bloquear
Evento: Antes de aceptar. Cuando la situación es sospechosa pero puede ser legítima, pregunta en lugar de prohibir.
if C.ImportePrecioMinimoUnidad > 0 and C.ImportePrecioMinimoUnidad > C.ImportePrecioUnidad
if F.PromptYesNo('Precio demasiado bajo', 'El precio de venta por unidad es inferior al precio de venta mínimo. ¿Desea continuar?', 1) = 0
F.CancelEvent()
end if
end ifAsí protegen las líneas de venta el precio mínimo: vender por debajo se permite, pero nunca sin querer.
Un botón que crea un registro relacionado
Evento: Click, sobre un campo que actúa como botón. Guarda el registro actual y abre el alta del relacionado con los campos clave ya puestos.
F.Save()
if C.ReferenciaTipo.SeLePuedeImputarTiempo = 0
F.MsgBox('No se le puede imputar tiempo al tipo ' + C.ReferenciaTipo.TextoPrincipal, 1)
else
F.AddElement_Begin(S.Sections.ActividadEnTareasDeProyectos.ID)
F.AddElement_SetValue(S.Fields.ActividadEnTareasDeProyectos.ReferenciaTarea.ID, C.ID)
F.AddElement_SetValue(S.Fields.ActividadEnTareasDeProyectos.ReferenciaProyecto.ID, C.ReferenciaProyecto)
F.AddElement_Commit()
end ifEl F.Save() inicial importa: un registro nuevo aún no tiene C.ID utilizable hasta que se guarda. Este patrón (guardar, validar, AddElement_Begin → SetValue → Commit) es el botón "Agregar" de media interfaz de Dinaup: tickets desde el proyecto, actividades desde la tarea, asientos desde el cobro.
Filtrar las opciones de un desplegable
Evento: Aplicar filtro desplegable, sobre el campo de relación. Antes de mostrar opciones, el script acota qué registros aparecen.
F.Field_ListDropdownWarning('Mostrando direcciones activas del cliente seleccionado.', 1)
F.Field_DropdownApplyFilter(S.Fields.DireccionesDeEnviosBase.ReferenciaEntidad.ID, '=', C.ReferenciaCliente)
F.Field_DropdownApplyFilter(S.Fields.DireccionesDeEnviosBase.Activa.ID, '=', 1)Los filtros se encadenan y pueden depender de otros campos del formulario: aquí las direcciones se filtran por el cliente ya elegido. Es el evento más usado del núcleo: casi todo desplegable filtra por activos, por tipo o por el registro padre.
Bloquear campos con el motivo a la vista
Evento: Tick de recálculo o Recalcular listado. F.Field_SetLockedWithReason bloquea o desbloquea según una condición, y el usuario ve el porqué al pasar por el campo.
txt motivo = 'Únicamente puede seleccionar 1: Recurso o Producto'
num bloquearRecurso = 0
num bloquearProducto = 0
¿C.ReferenciaProducto <> '' ? v.bloquearRecurso = 1
¿C.ReferenciaRecurso <> '' ? v.bloquearProducto = 1
F.Field_SetLockedWithReason(S.Fields.VentasIngresosLista.ReferenciaProducto.ID, v.motivo, v.bloquearProducto)
F.Field_SetLockedWithReason(S.Fields.VentasIngresosLista.ReferenciaRecurso.ID, v.motivo, v.bloquearRecurso)El tercer parámetro activa (1) o levanta (0) el bloqueo, así que el mismo script sirve para los dos sentidos: se ejecuta en cada tick y el formulario siempre queda coherente. La variante F.Field_SetRequiredWithReason hace lo mismo con la obligatoriedad.
Recalcular un importe mientras se edita
Evento: Tick de recálculo. Mantiene un campo derivado al día sin esperar al guardado.
if C.TiempoDeActividad_AutoCalculo = 0 or C.ImporteBonoPrecioHorasinImpuestos = 0
C.ImporteBonoCosteDeTareaACliente = 0
else
@ Minutos de actividad a precio/hora del bono
C.ImporteBonoCosteDeTareaACliente = F.Round(C.TiempoDeActividad_AutoCalculo * (C.ImporteBonoPrecioHorasinImpuestos / 60), 2)
end ifRedondea siempre los importes derivados (F.Round(..., 2)): el usuario ve el mismo número que se guardará.
Ofrecer autocompletado en un campo de texto
Evento: Formulario Cargado. Sugiere valores canónicos en un campo de texto libre, sin convertirlo en desplegable cerrado.
F.Field_TextAddAutoComplete(S.Fields.ActividadesDeEmpresas.Clave.ID, '1 - Actividades sujetas al Impuesto sobre Actividades Económicas')
F.Field_TextAddAutoComplete(S.Fields.ActividadesDeEmpresas.Clave.ID, '2 - Actividades sujetas al IAE (Profesionales y Artísticas)')
F.Field_TextAddAutoComplete(S.Fields.ActividadesDeEmpresas.Clave.ID, '3 - Arrendadores de Locales de Negocios y garajes')El usuario puede escribir cualquier cosa, pero las opciones esperadas están a un clic. En el núcleo alimenta desde claves de la AEAT hasta tipos de vía de direcciones.
→ Scripts y eventos → C.: el registro del formulario → Funciones (F.) → Buenas prácticas de DinaScript
Espacios I., D. y A.
Los tres prefijos que devuelven valores reales en tiempo de ejecución: el registro que recorres, el entorno y el resultado de un algoritmo.
Buenas prácticas de DinaScript
Convenciones de estilo, rendimiento y diseño de algoritmos para que tus scripts se entiendan a la primera y no penalicen al guardar.