@utilia-os/sdk-js 1.7.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -179,6 +179,174 @@ console.log(stats.bySeverity); // { critical: 5, high: 10, ... }
179
179
  console.log(stats.byModule); // { auth: 3, payments: 7, ... }
180
180
  ```
181
181
 
182
+ ### Configuración pública de la organización
183
+
184
+ Desde la versión 1.10.0, puedes leer los datos públicos de la organización
185
+ (branding, valores fiscales por defecto, contacto) sin necesidad de permisos
186
+ de administración. Útil para auto-rellenar formularios de presupuestos,
187
+ conocer el impuesto local del tenant o mostrar el logo en un portal externo:
188
+
189
+ ```typescript
190
+ const settings = await sdk.organizationSettings.getPublicSettings();
191
+
192
+ console.log(settings.companyName); // "UTILIA"
193
+ console.log(settings.defaultCurrency); // "EUR"
194
+ console.log(settings.defaultTaxName); // "IVA"
195
+ console.log(settings.defaultTaxRate); // 21
196
+ console.log(settings.country); // "ES"
197
+ console.log(settings.timezone); // "Atlantic/Canary"
198
+ console.log(settings.logoUrl); // URL presignada fresca
199
+ ```
200
+
201
+ Campos incluidos: identidad corporativa, domicilio social y operativo,
202
+ canales de contacto dinámicos, datos bancarios, configuración fiscal por
203
+ defecto (impuesto, tasa, país, moneda), timezone, branding (colores, logos)
204
+ y la configuración visual personalizada para PDFs de presupuestos.
205
+
206
+ Los metadatos internos (id, createdAt, updatedAt, updatedById) y los emails
207
+ legacy (emailSupport, emailHr, etc.) no se exponen en esta respuesta; los
208
+ emails legacy se transforman automáticamente a `contactChannels` por
209
+ retrocompatibilidad.
210
+
211
+ > **Breaking change en v2.0.0**: se ha eliminado el campo `businessActivity`
212
+ > de `OrganizationPublicSettings`. La actividad económica ya no forma parte
213
+ > de la configuración general de la organización; se ha migrado al modelo
214
+ > `FiscalConfig.activityDesc`, disponible vía el endpoint
215
+ > `finance/fiscal-config` (se añadirá un método dedicado al SDK en próximas
216
+ > versiones). Si tu integración leía `settings.businessActivity`, debes
217
+ > migrar a la nueva ubicación.
218
+
219
+ ## Comentarios y firmas de presupuestos
220
+
221
+ Desde la versión 2.1.0, el SDK cubre los dos dominios centrales del flujo de
222
+ aprobación de presupuestos: la conversación entre equipo y cliente y la firma
223
+ electrónica con magic link.
224
+
225
+ ### Comentarios (`sdk.budgetComments`)
226
+
227
+ Dos visibilidades: `INTERNAL` (solo equipo) y `CLIENT` (visible también en el
228
+ portal del cliente). Las menciones con `mentionedUserIds` solo tienen efecto
229
+ cuando la visibilidad es `INTERNAL`.
230
+
231
+ ```typescript
232
+ import { UtiliaSDK } from '@utilia-os/sdk-js';
233
+
234
+ const sdk = new UtiliaSDK({ baseURL: 'https://os.utilia.ai/api', apiKey: '...' });
235
+
236
+ // Listar comentarios dirigidos al cliente
237
+ const page = await sdk.budgetComments.list(budgetId, {
238
+ visibility: 'CLIENT',
239
+ page: 1,
240
+ limit: 20,
241
+ });
242
+
243
+ // Crear un comentario interno con menciones
244
+ const comment = await sdk.budgetComments.create(budgetId, {
245
+ body: 'Revisar el descuento del item 2 antes de enviar al cliente.',
246
+ visibility: 'INTERNAL',
247
+ mentionedUserIds: ['6d1a4c6b-3f8b-4a0e-a0d1-b29f1f1c21cb'],
248
+ });
249
+
250
+ // Editar el propio comentario
251
+ await sdk.budgetComments.update(budgetId, comment.id, {
252
+ body: 'Revisar descuento y condiciones de pago.',
253
+ });
254
+
255
+ // Crear varios comentarios en lote, tolerante a fallos
256
+ const result = await sdk.budgetComments.bulkCreate(
257
+ budgetId,
258
+ [
259
+ { body: 'Primer comentario' },
260
+ { body: 'Segundo comentario', clientOperationId: 'op-2' },
261
+ ],
262
+ { idempotencyKey: 'migration-2026-04-17' },
263
+ );
264
+ console.log(result.summary); // { total: 2, ok: 2, failed: 0 }
265
+ ```
266
+
267
+ ### Firmas y magic link (`sdk.budgetSignatures`)
268
+
269
+ El flujo completo cubre la emisión del magic link, el listado y revocación, la
270
+ verificación de integridad de una firma ya registrada y la descarga del
271
+ certificado legal.
272
+
273
+ ```typescript
274
+ // Emitir un magic link (idempotente por email)
275
+ const link = await sdk.budgetSignatures.generateSigningLink(budgetId, {
276
+ signerEmail: 'cliente@empresa.com',
277
+ signerName: 'María García',
278
+ expiresInHours: 72,
279
+ sendEmail: true,
280
+ });
281
+
282
+ if (!link.reused && link.signingUrl) {
283
+ console.log('Enviar al cliente:', link.signingUrl);
284
+ }
285
+
286
+ // Listar los magic links vivos
287
+ const activeLinks = await sdk.budgetSignatures.listSigningLinks(budgetId);
288
+
289
+ // Revocar un link
290
+ await sdk.budgetSignatures.revokeSigningLink(budgetId, link.tokenId);
291
+
292
+ // Verificar la integridad de una firma ya registrada
293
+ const signatures = await sdk.budgetSignatures.list(budgetId);
294
+ const verification = await sdk.budgetSignatures.verify(
295
+ budgetId,
296
+ signatures[0].id,
297
+ );
298
+ if (!verification.valid) {
299
+ console.warn('El documento ha cambiado después de la firma.');
300
+ }
301
+
302
+ // Descargar el certificado legal
303
+ const pdf = await sdk.budgetSignatures.downloadCertificate(
304
+ budgetId,
305
+ signatures[0].id,
306
+ );
307
+ ```
308
+
309
+ ### Audit trail
310
+
311
+ Historial paginado de eventos del proceso de firma (emisión, visualización,
312
+ descarga del PDF, aprobación, rechazo, expiración, revocación y fallos):
313
+
314
+ ```typescript
315
+ const events = await sdk.budgetSignatures.getAuditTrail(budgetId, {
316
+ tokenId: link.tokenId,
317
+ limit: 100,
318
+ });
319
+ ```
320
+
321
+ ## OAuth y Sign In
322
+
323
+ Desde la versión 1.6.0, el SDK incluye soporte nativo para OAuth 2.1 con PKCE. Esto permite implementar "Iniciar sesión con UTILIA" en tu aplicación:
324
+
325
+ ```typescript
326
+ const sdk = new UtiliaSDK({
327
+ baseURL: 'https://os.utilia.ai/api',
328
+ oauth: {
329
+ clientId: 'client_xxxxxxxxxx',
330
+ redirectUri: 'http://localhost:3000/callback',
331
+ scopes: ['openid', 'profile', 'email'],
332
+ },
333
+ });
334
+
335
+ // Redirigir al usuario para autorizar
336
+ const authUrl = await sdk.oauth.getAuthorizationUrl();
337
+ window.location.href = authUrl;
338
+
339
+ // Opcionalmente, solicitar un tema específico para la pantalla de consentimiento
340
+ const darkUrl = await sdk.oauth.getAuthorizationUrl({ theme: 'dark' });
341
+ window.location.href = darkUrl;
342
+
343
+ // En la página de callback
344
+ const tokens = await sdk.oauth.handleCallback(code);
345
+ const userInfo = await sdk.oauth.getUserInfo();
346
+ ```
347
+
348
+ Documentación completa: https://os.utilia.ai/dashboard/docs/integraciones-sdk/sdk-js-guia-oauth
349
+
182
350
  ## Manejo de Errores
183
351
 
184
352
  ```typescript