Cliente Dinaup
Referencia de DinaupClientC: conexión, informes tipados, lectura y exportación de secciones, escritura con WriteOperation, archivos, correo, fichajes y estructura Flex.
DinaupClientC es el cliente de la API de Dinaup en el paquete Dinaup. Consulta informes, lee, exporta y escribe secciones, y maneja archivos, anotaciones, documentos dinámicos, correo, sesiones, fichajes y la estructura Flex.
Antes de empezar
- Dos paquetes NuGet:
Dinaupy tu biblioteca MyDinaup. Los ejemplos usanDemoUp.MyDinaup, un modelo de ejemplo: en tu proyecto cambia el prefijo por el de tu empresa. - Tres credenciales: el endpoint
https://api.dinaup.com/v2/<clave de conexión>, con la clave de conexión que muestra la app Desarrollo de Play, y la clave pública y la secreta de una clave API creada en Administración → Claves API. La clave API hereda los permisos de su usuario. Ver Claves API. - La clave secreta solo se muestra una vez al crearla. Para no dejarla en el código, guárdala en el Vault.
using Dinaup; // DinaupClientC, WriteOperation, extensiones
using static DemoUp.MyDinaup.Reports.FuncionalidadD; // informes tipados (APIVentasC...)
using static DemoUp.MyDinaup.SectionsD; // secciones tipadas (EntidadesD, ProductosD...)Conectar y operar
Instala
dotnet add package Dinaup
dotnet add package DemoUp.MyDinaupConecta
var client = await DinaupClientC.ConnectAsync(
endPoint: "https://api.dinaup.com/v2/tu-codigo",
publicKey: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
secretKey: "tu-secret-key-aqui"
);
if (client == null || client.IsConnected == false)
throw new Exception("No se pudo conectar a Dinaup");ConnectAsync y su variante síncrona Connect crean el cliente, lo inicializan y comprueban la conexión. También vale new DinaupClientC(endPoint, publicKey, secretKey, defaultUserId) seguido de Initialize() o InitializeAsync(timeoutMs), o new DinaupClientC(settings) con un DinaupClientSettings. StartAutoPing() comprueba la conexión cada 30 segundos. Con las credenciales en el Vault, ver Vault.
Opera
var ventasReport = new APIVentasC();
await ventasReport.ExecuteQueryAsync(client, page: 1, resultsPerPage: 50);
foreach (var row in ventasReport.Rows)
Console.WriteLine($"{row.NumeroDeFacturaCompleto}: {row.Total}");var data = new Dictionary<string, string>
{
{ SeccionDePruebasAPID.SeccionDePruebasAPIES.TextoPrincipal, $"Prueba {Guid.NewGuid()}" }
};
var wOp = new WriteOperation("", data); // "" es un alta; con el Guid de un registro, una edición
await client.RunWriteOperationAsync(SeccionDePruebasAPID._SectionIDGUID, wOp, false);
wOp.EnsureSuccess(); // lanza si falló o no se ejecutó
Guid newId = wOp.WriteOperationResult.RowID;Tres identificadores de sección en MyDinaup
SeccionD._SectionID es el GUID como string; SeccionD._SectionIDGUID y SeccionD.SeccionES._SectionID son Guid. Las escrituras y RowsGetAsync piden Guid; los informes y los componentes DinaZen, string.
Tiempos de espera y reintentos
Cada petición espera CONFIG_TIMEOUT (30.000 ms por defecto), salvo las que fijan su propio tiempo, como ExecuteRawFunctionAsync(functionName, params, timeout) con un timeout positivo.
Ante un 429, el cliente espera lo que diga Retry-After (1 segundo si no viene) y repite una vez. Un 503 solo se repite en las lecturas, nunca en una escritura. Si la espera pasa de 5 segundos o no cabe en el tiempo que queda, devuelve el error sin repetir.
Informes
MyDinaup genera una clase API{Nombre}C por informe, heredera de DinaupReportBase, en {Empresa}.MyDinaup.Reports.{Categoria}D. La categoría es la carpeta del informe en Flex: en DemoUp.MyDinaup, Reports.FuncionalidadD trae APIVentasC, APIEntidadesC, APIImpuestosC y APISeccionDePruebasAPIC.
ExecuteQueryAsync(dinaupClient, page, resultsPerPage, querysearch, adminMode, includeFiles, includeFieldsDetails) ejecuta una página y deja las filas tipadas en Rows y, por id, en RowsDic. resultsPerPage vale 2.000 por defecto. querysearch busca en los campos de texto, como el buscador de la interfaz.
var report = new APISeccionDePruebasAPIC();
report.AddFilter(SeccionDePruebasAPID.SeccionDePruebasAPIES.ValorEntero, "=", 3);
report.AddOrder(SeccionDePruebasAPID.SeccionDePruebasAPIES.ValorEntero, true); // descendente
await report.ExecuteQueryAsync(client, page: 1, resultsPerPage: 10);| Método | Qué añade |
|---|---|
AddFilter(campo, operador, valor) | Filtro por campo. Admite string, int, decimal, double, bool, Guid, DateTime, DateOnly y TimeOnly. Dos filtros sobre el mismo campo se combinan con OR. |
AddFilterBetween(campo, desde, hasta) | Entre dos valores: string, int, decimal, DateOnly o DateTime. |
AddFilterDateRangeOverlapFilter(campoInicio, campoFin, desde, hasta) | Rangos de fechas que se solapan con el pedido. |
AddFilterIn(campo, valores) | Uno de varios valores (Guid[], int[] o string[]). Un solo valor se envía como =; la lista vacía no filtra. |
AddOrder(campo, descendente) | Orden. |
AddVariable(clave, valor) | Variable del informe: string, Guid, int, decimal, bool, DateTime o DateOnly. |
ContainsFilter(campo), ContainsVariable(clave) | Si ya hay un filtro sobre ese campo o esa variable. |
Para filtrar por un campo de la sección relacionada, la clave es una ruta de cuatro tramos: sección, campo de referencia, sección relacionada y campo de esa sección.
var relationKey =
SeccionDePruebasAPID.SeccionDePruebasAPIES._SectionID.STR() + "." +
SeccionDePruebasAPID.SeccionDePruebasAPIES.ReferenciaAutorDelAlta + "." +
EntidadesBaseD.EntidadesBaseES._SectionID.STR() + "." +
EntidadesBaseD.EntidadesBaseES.NombrePersonalRazonSocial;
report.AddFilter(relationKey, "=", "Ana López");Cada informe trae los tiempos del servidor (DatabaseTimeMS, PrepareTimeMS, PostProcessTimeMS y su suma, ServerTimeMS) y un TraceId para pedir soporte. Valen 0 o vacío hasta la primera consulta.
Paginación
Pide páginas hasta que una vuelva con menos filas que resultsPerPage: esa es la última. CurrentPage dice qué página tienes cargada. Para saber si hay más de las que muestras, pide una de más.
const int filasPorPagina = 300;
var report = new APISeccionDePruebasAPIC();
report.RequestParams.GetPageSummary = false; // sin recuento
for (int pagina = 1; ; pagina++)
{
await report.ExecuteQueryAsync(client, pagina, filasPorPagina);
foreach (var row in report.Rows) { /* procesar */ }
if (report.Rows.Count < filasPorPagina) break;
}No pagines con TotalPages ni ExecuteQuery_NextPageAsync
TotalPages y TotalResults están marcadas [Obsolete]: salen de un recuento aparte que, sobre un filtro sin índice, no llega a tiempo. Entonces TotalPages vale -1, ExistNextPage dice que no hay más y ExecuteQuery_NextPageAsync() se queda en la primera página.
Para todas las filas de un informe, usa LoadAllRowsAsync: sin filas repetidas ni saltadas.
Columnas ausentes en la respuesta
Si tu modelo declara una columna que el servidor ya no devuelve, el informe lanza una excepción. Con TolerateMissingColumns en true, registra un aviso y deja esas propiedades en su valor por defecto. La solución de fondo es regenerar MyDinaup.
report.TolerateMissingColumns = true; // un informe
DinaupReportSettings.TolerateMissingColumns = true; // todos los del proceso (por defecto, false)Sin MyDinaup
Report_GetAsync(new ReportRequestParameters(reportId)) ejecuta un informe por su GUID y devuelve un ReportResponse sin tipar (Report con la definición, DataList con las filas). ListReportsAsync(filtroCategoria) lista los informes disponibles.
Secciones
MyDinaup genera una clase {Seccion}D por sección con lectura directa:
var pais = await PaisesD.GetRowByIdAsync(client, paisId);
var parametros = new RowsRequestParameters(PaisesD.PaisesES.CodigoDePaisAlfabeticoDe2Caracteres, "=", "ES");
var paises = await PaisesD.GetRowsAsync(client, parametros); // List<PaisesC>
// Cabecera y líneas en una llamada: cada registro es MainRow más ListRows
var asientos = await AsientosContablesD.GetRowsWithListAsync(client, new RowsRequestParameters(asientoId));RowsRequestParameters se construye con un id, una lista de ids, un campo con operador y valor, o varios FilterCondition; varios arrays de condiciones se combinan con OR. QuerySearch, Limit, Skip e IncludeAnnotationsComments afinan la petición. Limit vale 100: para más filas, pagina con Skip.
Los campos de referencia llegan como DinaupBasicInformation: Id y SectionID del registro relacionado y su texto principal en Title (o Label). ToWriteOperationValue() da el texto que espera una escritura.
GetRowsAsync trae la sección entera y los textos de sus relaciones, así que cuesta más que un informe. Para listados, usa informes; para volumen, PG Sync.
Sin MyDinaup, RowsGetAsync(sectionId, includeList, parameters) devuelve las filas sin tipar. GetHistoryChanges(sectionId, rowId, campo) lista el histórico de cambios de un registro y GetBacklinksAsync(sectionId, rowId), quién lo referencia.
Exportar una sección a CSV
ExportAsync vuelca una sección a un CSV en el servidor y devuelve un ExportDTO con su URL firmada. Es la única lectura del cliente sin tope de filas.
// Toda la sección
var export = await client.ExportAsync(ProductosD._SectionIDGUID);
// Algunas columnas y filas
var columnas = new[] { ProductosD.ProductosES.TextoPrincipal, ProductosD.ProductosES.ReferenciaCodigoDeBarras };
var filtro = new List<FilterCondition> { new FilterCondition(ProductosD.ProductosES.Eliminado, "=", "0") };
var parcial = await client.ExportAsync(ProductosD._SectionIDGUID, columnas, filtro);
// Lo que cambió desde el export anterior: encadena con NextFromUtc
var cambios = await client.ExportAsync(ProductosD._SectionIDGUID, export.NextFromUtc);
if (cambios.State == ExportStateE.Ready)
{
var csv = await client.DownloadExportAsync(cambios);
foreach (var fila in csv.Rows)
Console.WriteLine(fila[ProductosD.ProductosES.TextoPrincipal]);
}| Miembro | Qué hace |
|---|---|
ExportAsync(sectionId, fromUtc) | Todas las columnas exportables. Con fromUtc, solo las filas con cambios desde esa fecha, bajas incluidas. |
ExportAsync(sectionId, columns, fromUtc) | Solo esas columnas, en ese orden. Pedir una que no se exporta es un error con la lista de las que no valen. |
ExportAsync(sectionId, columns, filter, fromUtc) | Filtra con condiciones en AND (=, <>, >, <, >=, <=); varias = sobre el mismo campo son un IN. |
ExportStateAsync(exportId) | El estado de una exportación ya iniciada. |
DownloadExportAsync(export) | Descarga el fichero: un ExportResult con Columns, TotalRows y Rows, legibles por nombre de campo. |
ExportDTO trae State (Working, Ready, Failed o Busy), ExportId, Url, Rows, Bytes, NextFromUtc, Filter y Message. Dinaup hace una exportación a la vez por empresa. Si el fichero no está listo, ExportAsync devuelve Working: consulta con ExportStateAsync y descárgalo en cuanto esté Ready, porque el resultado no se guarda indefinidamente.
En el CSV no salen la lista de la sección ni los campos de contraseña, confidenciales, eliminados u obsoletos. Para las líneas, exporta la sección de lista y crúzala con su registro principal. Con fromUtc y filtro a la vez, una fila que deja de cumplir el filtro no sale en el siguiente incremental: para sincronizar, filtra en destino.
Escritura
Las altas y las ediciones viajan en un WriteOperation: el id del registro y un diccionario campo a valor. Un id vacío ("" o Guid.Empty) es un alta; un id existente, una edición; un id que no existe, un error.
Los valores viajan como texto: decimal con punto y sin separador de miles ("1234.5"), booleano "1" o "0", fecha y hora "yyyy-MM-dd HH:mm:ss", fecha "yyyy-MM-dd", hora "HH:mm:ss" y referencia vacía como "". .STR() y .ToSQL() ya dan ese formato.
RunWriteOperationAsync devuelve un WriteOperationResponse: IsSuccess, UserError (el error de cada fila o, sin respuesta, el HTTP), Results, los contadores Cantidad_NuevosEnSeccionPrincipal y Cantidad_ActualizadosEnSeccionPrincipal y TiempoTotal en milisegundos. Cada WriteOperation recibe su WriteOperationResult con Confirmed, RowID y AError. resp.EnsureSuccess() lanza UserError; wOp.EnsureSuccess() lanza el error de esa fila o "No se ha ejecutado la operación.".
Un rechazo de negocio no lanza excepción
Si el servidor rechaza la fila por validación, la operación vuelve con Confirmed en false y el motivo en AError. Un try/catch no lo detecta: comprueba el resultado.
Un timeout no significa que no se guardó
Si una escritura agota CONFIG_TIMEOUT, el registro puede estar guardado: repetirla a ciegas duplica datos. Consulta antes de reintentar.
Scripts
El tercer parámetro de RunWriteOperationAsync (withsSripts) decide si el servidor ejecuta los scripts de la sección. Con true, la escritura se comporta como el formulario: scripts, validaciones, autorrellenados y campos calculados. Con false, los valores entran tal cual, con histórico. Con scripts, Dinaup procesa las operaciones de una en una: lanzar lotes en paralelo no acelera. Qué hace cada modo con los autorrellenados, el orden de los campos y las líneas, en Escribir en secciones.
Líneas, un campo y otras claves
-
Líneas. En secciones con lista, cada línea va como diccionario en
DataListRows, en la misma operación que la cabecera. En un registro existente, cada línea lleva su"id": el Guid de una línea la edita, vacío crea una nueva y"eliminado"a"1"la borra. Las que no envías no cambian.var wOp = new WriteOperation(rowId); // la cabecera, aunque no cambie ningún campo suyo wOp.DataListRows.Add(new Dictionary<string, string> { { "id", lineaId.ToString() }, { SeccionDePruebasAPIListaD.SeccionDePruebasAPIListaES.TextoPrincipal, "Línea corregida" } }); wOp.DataListRows.Add(new Dictionary<string, string> { { "id", otraLineaId.ToString() }, { "eliminado", "1" } }); await client.RunWriteOperationAsync(SeccionDePruebasAPID._SectionIDGUID, wOp, false);Se escribe siempre contra la sección principal: escribir contra la sección de lista no está soportado.
-
Un solo campo.
RunInlineWriteOperationAsync(sectionId, rowId, campo, valor). -
Relación por texto. Sin el Guid del registro relacionado, escribe
[Campo=Valor]y el servidor lo busca en la sección relacionada. Solo resuelve campos cuyo nombre interno empieza pornombreo porpr_.DinaupBasicInformation.SetDynamicSelector(campo, valor)construye el texto. Si no encuentra ningún registro, rechaza la operación entera, con el lote, sin escribir nada.{ ProductosD.ProductosES.ReferenciaUnidadDeMedidaPesoBase, "[nombre=Kilogramos]" } -
Otra clave.
mainKeyidentifica el registro por otro campo único (un SKU) en vez de porid;listKeyhace lo mismo con las líneas.await client.RunWriteOperationAsync(ProductosD._SectionIDGUID, wOp, false, mainKey: ProductosD.ProductosES.ReferenciaCodigoDeBarras); -
Filas tipadas.
RunWriteOperationAsync(fila, withsSripts)acepta unDinaupRowBase, una lista o una cabecera con sus líneas.fila.ToWriteOperation()construye elWriteOperation.
Por lotes
Una lista de WriteOperation viaja en una llamada. Sirve para crear y para actualizar: id vacío crea, id existente actualiza.
var operaciones = externos.Select(e => new WriteOperation(e.DinaupId ?? Guid.Empty, new Dictionary<string, string>
{
{ ProductosD.ProductosES.ReferenciaCodigoDeBarras, e.SKU },
{ ProductosD.ProductosES.TextoPrincipal, e.Nombre }
})).ToList();
foreach (var lote in operaciones.Chunk(DinaupClientC.MaxItemsPerWriteOperation))
{
var resp = await client.RunWriteOperationAsync(ProductosD._SectionIDGUID, lote, false);
resp.EnsureSuccess();
}- Cada llamada admite 25 operaciones (
MaxItemsPerWriteOperation) y 2.500 elementos contando las líneas (MaxTotalItemsPerWriteOperation). Una lista vacía se rechaza. - Todas las operaciones llevan el mismo juego de campos: si no, el SDK lanza
ArgumentExceptiony no escribe ninguna. Si un campo no aplica a una fila, envíalo vacío o agrupa las filas por columnas y haz una llamada por grupo. El vacío es un valor: en una edición borra lo guardado y en un alta con scripts pisa el autorrellenado. Agrupa en ediciones y cuando el campo lo rellena el servidor. - Por defecto (
allOrNone: false) no se deshace nada: si una operación falla, las demás se escriben. Reintenta solo las que no volvieron conConfirmed. ConallOrNone: trueel servidor deshace el lote entero si alguna falla; con scripts, rechaza la llamada (E-6191).
Archivos
Sube archivos desde memoria o desde una URL y firma URLs para servirlos. El tamaño máximo es Limits.MaxFileSizeInBytes: 150 MB.
var upload = await client.File_UploadBytesAsync(bytes, "prueba.txt");
Guid fileId = upload.FileId; // upload.FileData: Name, Extension, Mime, SizeInBytes, CRC (SHA1), IsImage, url_original, url_1080 ... url_32
var desdeUrl = await client.File_UploadURLAsync("https://cdn.dinaup.com/dinaup/web/portal/img/dinabot_marca.png", "dinabot.png");
var signed = await client.File_SignURLGetAsync(fileId); // signed.url_original; signed.Expirado si caducóFiles_SignURLGetAsync(ids) firma varios a la vez, FileGetAsync(id) y FilesGetAsync(ids) devuelven los metadatos y UpdateSignedURL(html) refresca las URLs firmadas de un HTML por su atributo data-file-id.
Para no subir un archivo repetido, calcula su SHA1 con Dinaup.extensions.ToSHA1(bytes) y búscalo en el informe del índice de archivos:
var report = new APIIndiceDeArchivosEnSistemaC();
report.AddFilter("crcbase", "=", sha1);
await report.ExecuteQueryAsync(client, 1, 1, "", true, true); // includeFiles: true
var existente = report.Files.Values.FirstOrDefault();Anotaciones
Cada fila admite tres tipos de anotación (AnnotationTypeE): Files (1), documentos privados del registro; Comments (2), mensajes del equipo; y PublicGallery (3), archivos públicos en el CDN que cualquiera con el enlace puede ver.
var anotacion = new AnotationParameters(sectionId, rowId, AnnotationTypeE.Comments)
.WithText("Comentario con adjunto")
.WithFile(upload.FileId); // opcional
await client.Annotation_PutAsync(anotacion);
var resultado = await client.Annotations_GetAsync(sectionId, rowId, AnnotationTypeE.Comments);
foreach (var a in resultado.Annotations) { /* a.Text, a.Autor, a.AnnotationDate, a.AttachedFiles */ }Documentos dinámicos
Un documento dinámico es un guion que se ejecuta en el servidor y devuelve HTML, JSON u otro formato. Para leer datos, un informe es más barato. MyDinaup genera una clase por documento bajo DynamicDocuments.{Categoria}D:
var doc = new DynamicDocuments.APID.SesionC();
doc.SetVariableValue("ventaId", ventaId); // string, Guid, int, decimal, bool o DateOnly
var response = await doc.ExecuteAsync(client);
var html = response.Content; // también URL, Name, Status y MetadataSin MyDinaup, DynamicDocuments_ExecuteAsync(documentId) o DynamicDocuments_ExecuteAsync(documentId, parametros) ejecutan el documento por su GUID, y DynamicDocumentsList() lista los disponibles.
Contexto de ejecución
Con credenciales de aplicación, las operaciones no tienen usuario detrás. DinaupContext.WithUser fija uno para todo el bloque using: queda como autor del alta, en el histórico y en las anotaciones.
using (DinaupContext.WithUser(userId, "192.168.1.1", "Mozilla/5.0")) // IP y UserAgent opcionales
{
await client.RunWriteOperationAsync(sectionId, wOp, false);
}El contexto vale para el flujo asíncrono en curso y se restaura al salir del using. DinaupContext.CurrentSession devuelve la sesión activa.
Fichajes
- Jornada.
Timesheet_StatusAsync(employeeIdentifier)devuelve el estado del fichaje yTimesheet_ClockAsync(employeeIdentifier, fingerprintIp, fingerprintBrowser, fingerprintUrl, fingerprintId, fingerprintRaw)ficha entrada o salida con la huella del dispositivo. - Pausas.
Break_StatusAsync,Break_StartAsync(employeeIdentifier, breakTypeId, ...)yBreak_StopAsync, con la misma huella.
Correo
SendEmailAsync(parameters, timeoutMS) envía un correo desde Dinaup. El cuerpo es HTML y sale tal cual, sin plantilla ni firma. timeoutMS vale 30.000.
var correo = new SendEmailParameters("[email protected]", "Tu factura", cuerpoHtml)
{
Sender = "[email protected]",
AttachmentIds = new List<Guid> { upload.FileId }
};
var resp = await client.SendEmailAsync(correo);
if (resp.Sent == false)
throw new Exception(resp.PendingReason);SendEmailParameters admite además RecipientName, Cc, Bcc, ReplyTo, SenderName, EntityId, RelatedSectionId y RelatedRowId.
Sendertiene que ser de un dominio verificado de tu licencia. SinSender, sale delnoreply@del primer dominio verificado, nunca de una dirección@dinaup.com.- Como mucho 50 direcciones contando las copias y 10 adjuntos, por id de un archivo ya subido.
- Comprueba siempre
Sent: si el eco del servidor no coincide con lo pedido, valefalseyPendingReasondice por qué.Result.Fromes la dirección de salida. - En una instalación local (on-premise) el envío no está disponible y
PendingReasonlo indica.
Clave-valor de la empresa
KV_GetAsync(space, key) y KV_SetAsync(space, key, value) guardan pares en la sección Dinaup KV de la empresa, visibles y editables como cualquier dato. No caducan.
await client.KV_SetAsync("miapp", "modo", "produccion");
string modo = await client.KV_GetAsync("miapp", "modo"); // "" si no existe
await client.KV_SetAsync("miapp", "ajustes", ajustes); // un objeto viaja como JSON
var leidos = await client.KV_GetAsync<AjustesDTO>("miapp", "ajustes");- El espacio es libre y
""es el global. Dos apps en el mismo espacio pisan sus valores. - Espacio y clave, hasta 200 caracteres; el valor, hasta 100.000. Por encima,
ArgumentExceptionsin llamar al servidor. - Escribir
""deja el par vacío, no lo borra.
El almacén de tu app, compartido por todas las empresas, es MyAppKVClient: ver Apps multi-tenant.
Todos los métodos del cliente
| Familia | Métodos |
|---|---|
| Conexión | ConnectAsync y Connect (estáticos), Initialize(enableAutoPing), InitializeAsync(timeoutMs, enableAutoPing), InitializeWitOuthCheckConnections, setConfig, setDefaultHeaders, setDefaultParameters, PING(forzar), PingAsync, PingCmd, PingCmdWithExceptions, Reconnect, ReconnectAsync, StartAutoPing, StopAutoPing, HealthCheckAsync, CheckHealthAsync (IHealthCheck), IsConnected, DescripcionDeErrorDeConexion, CONFIG_TIMEOUT, CONFIG_MAX_ROWS_PAGE_REPORT, Dispose. |
| Llamadas directas | ExecuteRawFunctionAsync(functionName, params, timeout) ejecuta cualquier función de la API por nombre; ExecuteApiFunctionAsJsonAsync. |
| Informes y consultas | Report_GetAsync(ReportRequestParameters), ListReportsAsync(filtroCategoria), IAQuery_GetAsync (IAQuery), QuickQuery (QuickQuery), Dashboards_Get(dashId). El filtro guardado de un informe: GetReportFilterAsync(reportId), SaveReportFilterAsync(reportId, blocks, expectedVersion) y GetReportFilterOperatorsAsync(). |
| Filas | RowsGetAsync(sectionId, includeList, parameters), GetHistoryChanges(sectionId, rowId, field), GetBacklinksAsync(sectionId, rowId), FechaIAGetAsync(parameters). |
| Exportación | ExportAsync(sectionId, columns, filter, fromUtc) y sus sobrecargas, ExportStateAsync(exportId), DownloadExportAsync(export), ExportTimeoutMs (60.000). |
| Escritura | RunWriteOperation y RunWriteOperationAsync (por WriteOperation, lista, DinaupRowBase, lista de filas o cabecera con líneas; parámetros withsSripts, mainKey, listKey, allOrNone), RunInlineWriteOperationAsync(sectionId, rowId, field, value), VirtualFormToWriteOperation (estático), MaxItemsPerWriteOperation (25), MaxTotalItemsPerWriteOperation (2.500). |
| Archivos | File_UploadBytesAsync, File_UploadURLAsync (y sus variantes síncronas), File_SignURLGetAsync(id, cachear, onlycache), Files_SignURLGetAsync(ids), File_SignURLInTextGet(html), UpdateSignedURL(html), FileGetAsync(id, disablecache), FilesGetAsync(ids), File_GetListAsync(ids), File_GetURLPublicFile(keywordLic, publicFileId, fileName), File_IsPublicFile(id) (estático), DownloadFileURL(url). |
| Anotaciones | Annotation_PutAsync(AnotationParameters), Annotations_GetAsync(sectionId, rowId, type). |
| Documentos dinámicos | DynamicDocuments_ExecuteAsync(documentId), DynamicDocuments_ExecuteAsync(documentId, params), DynamicDocuments_ExecuteAsync(DynamicDocumentGetRequestParameters), DynamicDocumentsList(). |
| Esquema | GetBusinessSchem() (todo el esquema), GetBusinessSchemaFields(sectionId, includeAll) (los campos de una sección con su maqueta), GetCorruptObjectsAsync() (objetos de estructura rotos y su motivo). |
| Estructura Flex: lectura | Flex_GetObjectAsync(objectType, id), Flex_ListObjectsAsync(objectType, sectionId, includeDeleted, includeObsolete, search), Flex_GetEditablesAsync(objectType) y Flex_GetEditablesAllAsync() (contrato de escritura de cada tipo), Flex_GetEnumAsync(enumName), Flex_GetFieldEnumAsync(fieldId), Flex_GetEnumsAllAsync(), Flex_GetScriptFunctionsAsync() (funciones de DinaScript con su firma), Flex_GetRoutesAsync(prefix, sectionId, path) (qué se puede escribir en un script de una sección), Flex_GetQuestionsAsync(objectType, id) (preguntas de un informe, documento o algoritmo). |
| Estructura Flex: escritura | Flex_ValidateCodeAsync(code, sectionId, eventFields, relatedSectionId, algorithmId, algorithmType, isFilter, mainRowsToProcess, relatedRowsToProcess) compila un script sin guardarlo y devuelve los fallos con su rango de caracteres; con algorithmId o algorithmType valida la fórmula de un algoritmo y con isFilter, su filtro. Flex_CreateObjectAsync(objectType, parentId, patch, actorId), Flex_UpdateObjectAsync(objectType, id, patch, expectedVersion, dryRun, ...), Flex_SetQuestionsAsync(objectType, id, questions, expectedVersion, dryRun, actorId), Flex_DeleteObjectAsync (borrado lógico), Flex_UndeleteObjectAsync, Flex_ApplyLayoutAsync (posiciones de campo en lote atómico o sueltas) y Flex_ConsolidateAsync() (hace efectivos los cambios pendientes del esquema). Admiten dryRun donde tiene sentido. Una sección se retira con Flex_UpdateObjectAsync(FlexObjectTypes.Sections, id, patch) y obsoleto a "1": sigue en la base y sale del producto; en una sección de lista se rechaza. Al crear campos (FlexObjectTypes.Fields) o columnas de informe (FlexObjectTypes.ReportColumns), consolidar a "0" crea sin consolidar: el objeto no se usa hasta Flex_ConsolidateAsync(), que se llama una vez al final. Qué es cada objeto, en Dinaup Flex. |
| Paneles | GetDashboardForEditAsync(dashboardId), SaveDashboardAsync(dashboardId, name, iconId, accessAll, accessRecords), DeleteDashboardAsync(dashboardId) (baja lógica que no se deshace desde fuera; devuelve "" o el motivo del rechazo), AddDashboardWidgetAsync(dashboardId, kind, target, gridColumns), SetDashboardWidgetModeAsync, DeleteDashboardWidgetAsync, SetDashboardPositionsAsync. |
| Roles | GetRolesAsync(), GetRoleAsync(rolId), SaveRoleAsync(RoleDTO), CreateRoleAsync(name, descripcion) (nace sin permisos), DeleteRoleAsync (baja lógica), RestoreRoleAsync. |
| Sesiones y cuentas | Session_SignInAsync, Session_SignOutAsync, Session_GetDetailsAsync, Session_GetDetailsWithCacheCompatibilityAsync, Session_GetIfCached, Session_CheckTwoFactor, Session_CreateLoginCodeAsync, Session_SignInWithCodeAsync, Session_RegisterAccountAsync, Session_ConfirmAccountRegistrationAsync, Session_RecoverPasswordAsync, Session_CreatePasswordRecoveryCodeAsync, Session_ChangePasswordWithCodeAsync, Session_EntitiesIdWithActiveSession, DefaultSession, DefaultSessionUpdateAsync. Firmas y flujo en Apps multi-tenant. |
| Fichajes | Timesheet_StatusAsync, Timesheet_ClockAsync, Break_StatusAsync, Break_StartAsync, Break_StopAsync. |
| Correo | SendEmailAsync(parameters, timeoutMS). |
| Clave-valor de la empresa | KV_GetAsync(space, key), KV_GetAsync<T>(space, key), KV_SetAsync(space, key, value), KV_SetAsync<T>(space, key, value). |
| Validación fiscal | CheckVATViesAsync(vatid), CheckVATAEATAsync(vatid, name). Ver Dinaup.Validations. |
| Módulos Flex | GetModuleGalleryAsync() y GetModulePlanAsync(licserie, canal, version) (qué instalaría, sin cambiar nada). |
| Formularios virtuales | FormOpenAsync, FormOpenDataFlowAsync, FormUpdate, FormSave, FormCancel, FormSendClick, FormNewListItem, FormRemoveListItem, FormAutoCumpleteDataFlow, GetOpenedWindows, OpenedFormAddRelation. Son el motor de DnzFormView en DinaZen; en una app normal no se llaman a mano. FormSave envía también las ediciones pendientes y lanza Exceptions.FormClosedException si el formulario ya no está abierto. VirtualFormDTO.RowExists es true cuando el registro existe. |
Otros canales
| Necesitas | Canal |
|---|---|
| Probar una petición sin código ni datos reales | Zona de pruebas de Play |
| Los IDs de secciones, campos e informes | Esquema de Play |
| La API desde cualquier lenguaje | Referencia de la API REST |
| Que Dinaup avise a otro programa de un cambio | Webhooks salientes o Eventos Redis |
| Leer volumen por SQL | PG Sync |