# DinaScript

DinaScript es el lenguaje de programación propio de Dinaup Flex que permite crear **lógica personalizada**, **automatizaciones** y **documentos dinámicos** dentro de la plataforma. Es un lenguaje diseñado para ser simple pero potente, permitiendo desde operaciones básicas hasta integraciones complejas con APIs externas.

<br>

### Conceptos Fundamentales

#### 1. Espacios de Nombres (Namespaces)

DinaScript organiza sus funciones en **espacios de nombres** que agrupan funcionalidades relacionadas:

* **`F.`** - Funciones generales (manipulación de datos, fechas, texto, etc.)
* **`S.`** - Sistema (acceso a metadatos y configuración de Dinaup)
* **`I.`** - Iterador (datos del registro actual en procesamiento)
* **`D.`** - Datos globales del sistema
* **`V.`** - Variables locales o globales del script
* **`A.`** - Opciones avanzadas de algoritmos

## Sintaxis de DinaScript

### 🔤 Declaración de Variables

#### Tipos de Variables (Solo 2 tipos)

```javascript
// TEXTO (txt) - Para todo tipo de cadenas, fechas, booleanos, GUIDs
txt nombre = "Juan"
txt apellido = 'García'
txt vacio = ""
txt fecha = "2024-12-25"      // Fechas como texto
txt guid = "550e8400-e29b-41d4-a716-446655440000"

// NÚMERO (num) - Para enteros y decimales
num entero = 42
num decimal = 3.14159
num negativo = -10
num cero = 0
num booleano = 1              // 1 = true, 0 = false
```

#### Variables del Sistema

```javascript
// v. = Variables locales (las que tú creas)
txt miTexto = "Hola"
num miNumero = 100

// I. = Iterador (datos del registro actual en un bucle)
txt clienteNombre = I.Clientes.Nombre
num clienteSaldo = I.Clientes.Saldo
 
```

### ⚡ Operadores

#### Operadores Aritméticos

```javascript
num suma = 10 + 5          // 15
num resta = 10 - 5         // 5
num multiplicacion = 10 * 5 // 50
num division = 10 / 5      // 2
num modulo = 10 % 3        // 1 (resto)

// Operaciones combinadas
num resultado = (10 + 5) * 2 - 3    // 27
```

#### Operadores de Comparación

```javascript
// Igual
if v.edad = 18              // Igual a
if v.nombre == "Juan"       // También funciona

// Diferente
if v.edad <> 18             // Diferente de
if v.nombre != "Juan"       // También funciona

// Mayor y menor (solo con números)
if v.edad > 18              // Mayor que
if v.edad >= 18             // Mayor o igual que
if v.edad < 18              // Menor que
if v.edad <= 18             // Menor o igual que

// Comparación de texto
if v.estado = "activo"
if v.estado <> ""           // No vacío
```

#### Operadores Lógicos

```javascript
// AND - Todas las condiciones deben ser verdaderas
if v.edad >= 18 and v.tieneLicencia = 1
    F.Write("Puede conducir")
end if

// OR - Al menos una condición debe ser verdadera
if v.dia = "sábado" or v.dia = "domingo"
    F.Write("Es fin de semana")
end if
 
```

### 🔀 Estructuras de Control

#### IF Simple

```javascript
if v.temperatura > 30
    F.Write("Hace calor")
end if
```

#### IF-ELSE

```javascript
if v.edad >= 18
    F.Write("Mayor de edad")
else
    F.Write("Menor de edad")
end if
```

#### IF-ELSEIF-ELSE

```javascript
if v.nota >= 9
    F.Write("Sobresaliente")
elseif v.nota >= 7
    F.Write("Notable")
elseif v.nota >= 5
    F.Write("Aprobado")
else
    F.Write("Suspenso")
end if
```

#### IF Anidados

```javascript
txt tipoPlan = "premium"
num esMiembro = 1

if v.esMiembro = 1
    if v.tipoPlan = "premium"
        F.Write("Acceso completo")
    elseif v.tipoPlan = "basico"
        F.Write("Acceso limitado")
    else
        F.Write("Plan no válido")
    end if
else
    F.Write("No es miembro")
end if
```

### 🔄 Bucles y Procesamiento

#### ProcessDataList (bucle sobre registros)

```javascript
F.DataListLoad(S.Sections.Productos.ID, 1, 999999)
F.DataListLoadAddFilter(S.Sections.Productos.ID, S.Fields.Productos.Activo.ID, '=', 1)

num totalProductos = 0
num productosConBajoStock = 0

F.ProcessDataList_Ini(S.Sections.Productos.ID)
    v.totalProductos = v.totalProductos + 1
    
    // Verificar stock
    if I.Productos.Stock < 10 and I.Productos.Importante = 1
        F.Write(F.Concat("ALERTA: ", I.Productos.Nombre, " bajo stock"))
        v.productosConBajoStock = v.productosConBajoStock + 1
    elseif I.Productos.Stock = 0
        F.Write(F.Concat("SIN STOCK: ", I.Productos.Nombre))
    end if
F.ProcessDataList_End
```

### 📝 Trabajando con Texto

#### Concatenación

```javascript
// Usando F.Concat
txt nombre = "Juan"
txt apellido = "García"
txt mensaje = F.Concat("Hola ", v.nombre, " ", v.apellido)

// Concatenación múltiple
txt calle = "Gran Vía"
txt numero = "123"
txt ciudad = "Madrid"
txt codigoPostal = "28001"
txt direccion = F.Concat4(v.calle, " ", v.numero, ", ", v.ciudad, " ", v.codigoPostal)

// Con condiciones
num hora = 14
txt saludo = ""
if v.hora < 12
    v.saludo = F.Concat("Buenos días, ", v.nombre)
elseif v.hora < 20
    v.saludo = F.Concat("Buenas tardes, ", v.nombre)
else
    v.saludo = F.Concat("Buenas noches, ", v.nombre)
end if
```

#### Comparación de Texto

```javascript
// Comparación exacta
txt nombre = "Juan"
if v.nombre = "Juan"
    F.Write("Es Juan")
end if

// Verificar si está vacío
txt email = ""
if v.email = ""
    F.Write("Email no proporcionado")
end if

if v.email <> ""
    F.Write("Email proporcionado")
end if

// Contiene texto (usando función)
txt descripcion = "Tarea urgente para hoy"
if F.Contains(v.descripcion, "urgente")
    F.Write("Tarea prioritaria")
end if

// Empieza o termina con
txt codigo = "ES12345"
if F.StartsWith(v.codigo, "ES")
    F.Write("Código español")
end if

txt archivo = "documento.pdf"
if F.EndsWith(v.archivo, ".pdf")
    F.Write("Es un PDF")
end if
```

### 🔢 Trabajando con Números

#### Comparaciones y Rangos

```javascript
num edad = 25

// Verificar rangos
if v.edad >= 0 and v.edad <= 17
    F.Write("Menor de edad")
elseif v.edad >= 18 and v.edad <= 65
    F.Write("Adulto")
elseif v.edad > 65
    F.Write("Tercera edad")
end if

// Validar valores
num precio = 100
num descuento = 15
num precioFinal = 0

if v.precio > 0
    if v.descuento >= 0 and v.descuento <= 100
        v.precioFinal = v.precio * (1 - v.descuento/100)
    else
        F.Write("Descuento no válido")
    end if
else
    F.Write("Precio no válido")
end if
```

#### Trabajando con Booleanos (como números)

```javascript
// true = 1, false = 0
num activo = 1
num verificado = 0
num tieneLicencia = 1

// Verificación simple
if v.activo = 1
    F.Write("Usuario activo")
end if

// Múltiples verificaciones
if v.activo = 1 and v.verificado = 1
    F.Write("Usuario activo y verificado")
end if

// Toggle (cambiar estado)
v.activo = 1 - v.activo  // Si era 1 pasa a 0, si era 0 pasa a 1

// Contador de condiciones verdaderas
num condicionesCumplidas = v.activo + v.verificado + v.tieneLicencia
if v.condicionesCumplidas >= 2
    F.Write("Al menos 2 condiciones cumplidas")
end if
```

### 📅 Trabajando con Fechas (como texto)

#### Comparación de Fechas

```javascript
// Las fechas se manejan como texto o mediante funciones F.
txt fechaHoy = F.Cast_DateToText(D.Dynamic.CurrentDate)
txt fechaVencimiento = "2024-12-31"

// Para comparar fechas, usar funciones F.
num diasDiferencia = F.DaysDifferenceBetweenDates(
    D.Dynamic.CurrentDate,
    F.Cast_TextToDate(v.fechaVencimiento)
)

if v.diasDiferencia < 0
    F.Write("Vencido")
elseif v.diasDiferencia = 0
    F.Write("Vence hoy")
elseif v.diasDiferencia <= 7
    F.Write("Vence esta semana")
else
    F.Write(F.Concat("Vence en ", F.Cast_NumToText(v.diasDiferencia), " días"))
end if
```

### 🚫 Manejo de Valores Vacíos/Cero

#### Verificación de Valores

```javascript
// Texto vacío
txt nombre = ""
if v.nombre = ""
    v.nombre = "Sin nombre"
end if

// Número cero
num cantidad = 0
if v.cantidad = 0
    F.Write("Cantidad no especificada")
end if

// Booleano (como número)
num activo = 0
if v.activo = 0
    v.activo = 1  // Activar por defecto
end if

// Verificación múltiple
txt valor1 = ""
txt valor2 = "algo"
num tieneValores = 0

if v.valor1 <> "" or v.valor2 <> ""
    v.tieneValores = 1
end if
```

### 💡 Patrones Comunes

#### Validación de Formulario

```javascript
num formularioValido = 1
txt errores = ""
txt nombre = ""
txt email = "test@test"
num edad = 15

if v.nombre = ""
    v.formularioValido = 0
    v.errores = F.Concat(v.errores, "- Nombre requerido\n")
end if

if v.email = "" or not F.Contains(v.email, "@")
    v.formularioValido = 0
    v.errores = F.Concat(v.errores, "- Email inválido\n")
end if

if v.edad < 18 or v.edad > 120
    v.formularioValido = 0
    v.errores = F.Concat(v.errores, "- Edad fuera de rango\n")
end if

if v.formularioValido = 1
    F.Write("Formulario enviado correctamente")
else
    F.Write(F.Concat("Errores encontrados:\n", v.errores))
end if
```

#### Switch-like con IF

```javascript
txt dia = "lunes"
txt tipo = ""

if v.dia = "lunes" or v.dia = "martes" or v.dia = "miércoles" or v.dia = "jueves" or v.dia = "viernes"
    v.tipo = "laborable"
elseif v.dia = "sábado" or v.dia = "domingo"
    v.tipo = "fin de semana"
else
    v.tipo = "día no válido"
end if
```

#### Conversión entre Tipos

```javascript
// Número a Texto
num cantidad = 42
txt cantidadTexto = F.Cast_NumToText(v.cantidad)

// Texto a Número
txt precio = "99.99"
num precioNum = F.Cast_TextToNum(v.precio)

// Booleano como número
num estaActivo = 1
txt estadoTexto = ""
if v.estaActivo = 1
    v.estadoTexto = "Activo"
else
    v.estadoTexto = "Inactivo"
end if
```

#### Cálculo con Condiciones

```javascript
// Sistema de puntos con múltiples criterios
num puntoBase = 100
num multiplicador = 1
txt categoria = "oro"
num esNuevoCliente = 0
num comprasEsteMes = 5

// Multiplicador por categoría
if v.categoria = "bronce"
    v.multiplicador = 1
elseif v.categoria = "plata"
    v.multiplicador = 1.5
elseif v.categoria = "oro"
    v.multiplicador = 2
elseif v.categoria = "platino"
    v.multiplicador = 3
end if

// Bonus adicionales
num bonus = 0
if v.esNuevoCliente = 1
    v.bonus = v.bonus + 50
end if

if v.comprasEsteMes >= 5
    v.bonus = v.bonus + 100
elseif v.comprasEsteMes >= 3
    v.bonus = v.bonus + 50
end if

// Cálculo final
num puntosFinales = (v.puntoBase * v.multiplicador) + v.bonus
```

#### Control de Flujo con Flags

```javascript
// Usar números como banderas (flags)
num continuar = 1
num error = 0
txt mensajeError = ""

// Validación paso a paso
txt codigoProducto = "PRD123"
num stock = 5
num cantidadSolicitada = 10

if v.codigoProducto = ""
    v.error = 1
    v.mensajeError = "Código de producto vacío"
    v.continuar = 0
end if

if v.continuar = 1 and v.stock < v.cantidadSolicitada
    v.error = 1
    v.mensajeError = "Stock insuficiente"
    v.continuar = 0
end if

if v.continuar = 1
    F.Write("Pedido procesado correctamente")
else
    F.Write(F.Concat("Error: ", v.mensajeError))
end if
```

### 📌 Notas Importantes sobre Variables

1. **Solo existen `txt` y `num`** - Todo lo demás se maneja con estas dos
2. **Booleanos son números** - `1` = true, `0` = false
3. **Fechas son texto** - Usar funciones F. para manipularlas
4. **GUIDs son texto** - Se almacenan como cadenas
5. **No hay arrays nativos** - Usar DataTables para colecciones
6. **Variables siempre con prefijo** - `v.` para locales, `I.` para iterador
7. **Conversión explícita** - Usar F.Cast\_\* para convertir entre tipos

<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.dinaup.com/desarrollo/flex/dinascript.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
