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: Dinaup y tu biblioteca MyDinaup. Los ejemplos usan DemoUp.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.MyDinaup

Conecta

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étodoQué 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]);
}
MiembroQué 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 por nombre o por pr_. 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. mainKey identifica el registro por otro campo único (un SKU) en vez de por id; listKey hace lo mismo con las líneas.

    await client.RunWriteOperationAsync(ProductosD._SectionIDGUID, wOp, false, mainKey: ProductosD.ProductosES.ReferenciaCodigoDeBarras);
  • Filas tipadas. RunWriteOperationAsync(fila, withsSripts) acepta un DinaupRowBase, una lista o una cabecera con sus líneas. fila.ToWriteOperation() construye el WriteOperation.

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 ArgumentException y 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 con Confirmed. Con allOrNone: true el 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 Metadata

Sin 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 y Timesheet_ClockAsync(employeeIdentifier, fingerprintIp, fingerprintBrowser, fingerprintUrl, fingerprintId, fingerprintRaw) ficha entrada o salida con la huella del dispositivo.
  • Pausas. Break_StatusAsync, Break_StartAsync(employeeIdentifier, breakTypeId, ...) y Break_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.

  • Sender tiene que ser de un dominio verificado de tu licencia. Sin Sender, sale del noreply@ 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, vale false y PendingReason dice por qué. Result.From es la dirección de salida.
  • En una instalación local (on-premise) el envío no está disponible y PendingReason lo 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, ArgumentException sin 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

FamiliaMétodos
ConexiónConnectAsync 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 directasExecuteRawFunctionAsync(functionName, params, timeout) ejecuta cualquier función de la API por nombre; ExecuteApiFunctionAsJsonAsync.
Informes y consultasReport_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().
FilasRowsGetAsync(sectionId, includeList, parameters), GetHistoryChanges(sectionId, rowId, field), GetBacklinksAsync(sectionId, rowId), FechaIAGetAsync(parameters).
ExportaciónExportAsync(sectionId, columns, filter, fromUtc) y sus sobrecargas, ExportStateAsync(exportId), DownloadExportAsync(export), ExportTimeoutMs (60.000).
EscrituraRunWriteOperation 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).
ArchivosFile_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).
AnotacionesAnnotation_PutAsync(AnotationParameters), Annotations_GetAsync(sectionId, rowId, type).
Documentos dinámicosDynamicDocuments_ExecuteAsync(documentId), DynamicDocuments_ExecuteAsync(documentId, params), DynamicDocuments_ExecuteAsync(DynamicDocumentGetRequestParameters), DynamicDocumentsList().
EsquemaGetBusinessSchem() (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: lecturaFlex_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: escrituraFlex_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.
PanelesGetDashboardForEditAsync(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.
RolesGetRolesAsync(), GetRoleAsync(rolId), SaveRoleAsync(RoleDTO), CreateRoleAsync(name, descripcion) (nace sin permisos), DeleteRoleAsync (baja lógica), RestoreRoleAsync.
Sesiones y cuentasSession_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.
FichajesTimesheet_StatusAsync, Timesheet_ClockAsync, Break_StatusAsync, Break_StartAsync, Break_StopAsync.
CorreoSendEmailAsync(parameters, timeoutMS).
Clave-valor de la empresaKV_GetAsync(space, key), KV_GetAsync<T>(space, key), KV_SetAsync(space, key, value), KV_SetAsync<T>(space, key, value).
Validación fiscalCheckVATViesAsync(vatid), CheckVATAEATAsync(vatid, name). Ver Dinaup.Validations.
Módulos FlexGetModuleGalleryAsync() y GetModulePlanAsync(licserie, canal, version) (qué instalaría, sin cambiar nada).
Formularios virtualesFormOpenAsync, 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

NecesitasCanal
Probar una petición sin código ni datos realesZona de pruebas de Play
Los IDs de secciones, campos e informesEsquema de Play
La API desde cualquier lenguajeReferencia de la API REST
Que Dinaup avise a otro programa de un cambioWebhooks salientes o Eventos Redis
Leer volumen por SQLPG Sync

En esta página