@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 +168 -0
- package/dist/index.d.mts +1412 -16
- package/dist/index.d.ts +1412 -16
- package/dist/index.js +1122 -37
- package/dist/index.mjs +1121 -37
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -102,10 +102,25 @@ interface LoginUrlResult {
|
|
|
102
102
|
/** Valor de state para protección CSRF */
|
|
103
103
|
state: string;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Opciones OIDC extendidas aceptadas por getLoginUrl() y loginWithPopup().
|
|
107
|
+
*/
|
|
108
|
+
interface OidcAuthorizationOptions {
|
|
109
|
+
/** Parámetro `prompt` de OIDC Core 1.0 §3.1.2.1. */
|
|
110
|
+
prompt?: 'none' | 'login' | 'consent' | 'select_account';
|
|
111
|
+
/** Sugerencia de email o identificador de usuario para el login. */
|
|
112
|
+
loginHint?: string;
|
|
113
|
+
/** Nonce para prevenir replay attacks en el ID token. */
|
|
114
|
+
nonce?: string;
|
|
115
|
+
/** Resource Indicator (RFC 8707) del token resultante. */
|
|
116
|
+
resource?: string;
|
|
117
|
+
/** Tiempo máximo en segundos desde la última autenticación activa. */
|
|
118
|
+
maxAge?: number;
|
|
119
|
+
}
|
|
105
120
|
/**
|
|
106
121
|
* Opciones para inicio de sesión OAuth mediante ventana emergente
|
|
107
122
|
*/
|
|
108
|
-
interface PopupLoginOptions {
|
|
123
|
+
interface PopupLoginOptions extends OidcAuthorizationOptions {
|
|
109
124
|
/** Parámetro state personalizado para protección CSRF */
|
|
110
125
|
state?: string;
|
|
111
126
|
/** Scopes a solicitar */
|
|
@@ -116,6 +131,35 @@ interface PopupLoginOptions {
|
|
|
116
131
|
height?: number;
|
|
117
132
|
/** Tiempo límite en milisegundos antes de rechazar (por defecto: 300000 = 5 min) */
|
|
118
133
|
timeout?: number;
|
|
134
|
+
/** Tema de la pantalla de consentimiento: 'light' o 'dark'. Si no se indica, usa la preferencia del usuario. */
|
|
135
|
+
theme?: 'light' | 'dark';
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Respuesta de introspección de token (RFC 7662 §2.2).
|
|
139
|
+
*/
|
|
140
|
+
interface IntrospectResponse {
|
|
141
|
+
active: boolean;
|
|
142
|
+
scope?: string;
|
|
143
|
+
client_id?: string;
|
|
144
|
+
username?: string;
|
|
145
|
+
token_type?: string;
|
|
146
|
+
exp?: number;
|
|
147
|
+
iat?: number;
|
|
148
|
+
sub?: string;
|
|
149
|
+
aud?: string;
|
|
150
|
+
iss?: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Datos de una aplicación OAuth autorizada por el usuario.
|
|
154
|
+
*/
|
|
155
|
+
interface AuthorizedApp {
|
|
156
|
+
clientId: string;
|
|
157
|
+
clientName: string;
|
|
158
|
+
clientUri: string | null;
|
|
159
|
+
logoUri: string | null;
|
|
160
|
+
scope: string;
|
|
161
|
+
authorizedAt: string;
|
|
162
|
+
lastUsedAt: string | null;
|
|
119
163
|
}
|
|
120
164
|
|
|
121
165
|
/**
|
|
@@ -139,12 +183,26 @@ interface UtiliaSDKConfig {
|
|
|
139
183
|
interface RequestConfig {
|
|
140
184
|
headers?: Record<string, string>;
|
|
141
185
|
params?: Record<string, unknown>;
|
|
186
|
+
/**
|
|
187
|
+
* Tipo esperado de la respuesta. Util para descargas binarias (PDF, CSV).
|
|
188
|
+
* Internamente mapea al `responseType` de Axios.
|
|
189
|
+
*/
|
|
190
|
+
responseType?: 'json' | 'arraybuffer' | 'blob' | 'text';
|
|
142
191
|
}
|
|
143
192
|
|
|
144
193
|
/**
|
|
145
194
|
* Servicio OAuth 2.1 con PKCE para el SDK de UTILIA OS
|
|
146
195
|
*/
|
|
147
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Opciones comunes para construir la URL de autorización.
|
|
199
|
+
*/
|
|
200
|
+
interface AuthorizationUrlOptions extends OidcAuthorizationOptions {
|
|
201
|
+
state?: string;
|
|
202
|
+
scopes?: string[];
|
|
203
|
+
/** Tema de la pantalla de consentimiento: 'light' o 'dark'. */
|
|
204
|
+
theme?: 'light' | 'dark';
|
|
205
|
+
}
|
|
148
206
|
/**
|
|
149
207
|
* Servicio que gestiona el flujo OAuth 2.1 con PKCE
|
|
150
208
|
*/
|
|
@@ -155,6 +213,8 @@ declare class OAuthService {
|
|
|
155
213
|
private readonly http;
|
|
156
214
|
/** Estado PKCE en memoria como fallback cuando el storage no soporta pendingState */
|
|
157
215
|
private _pendingState;
|
|
216
|
+
/** Promesa de refresco en curso para deduplicar llamadas concurrentes. */
|
|
217
|
+
private _refreshInFlight;
|
|
158
218
|
constructor(baseURL: string, config: OAuthConfig);
|
|
159
219
|
/**
|
|
160
220
|
* Genera la URL de autorización OAuth con PKCE y almacena el estado
|
|
@@ -162,26 +222,20 @@ declare class OAuthService {
|
|
|
162
222
|
*
|
|
163
223
|
* Este es el método recomendado para la mayoría de los casos.
|
|
164
224
|
*
|
|
165
|
-
* @param options - Opciones adicionales (state personalizado, scopes)
|
|
225
|
+
* @param options - Opciones adicionales (state personalizado, scopes, parámetros OIDC)
|
|
166
226
|
* @returns URL de autorización lista para redirigir al usuario
|
|
167
227
|
*/
|
|
168
|
-
getAuthorizationUrl(options?:
|
|
169
|
-
state?: string;
|
|
170
|
-
scopes?: string[];
|
|
171
|
-
}): Promise<string>;
|
|
228
|
+
getAuthorizationUrl(options?: AuthorizationUrlOptions): Promise<string>;
|
|
172
229
|
/**
|
|
173
230
|
* Genera la URL de inicio de sesión OAuth con PKCE.
|
|
174
231
|
*
|
|
175
232
|
* Método de control manual: devuelve codeVerifier y state que el desarrollador
|
|
176
233
|
* debe gestionar. Para un flujo automático, usar getAuthorizationUrl() en su lugar.
|
|
177
234
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
235
|
+
* Soporta los parámetros OIDC Core 1.0 §3.1.2.1: prompt, loginHint, nonce,
|
|
236
|
+
* maxAge y el Resource Indicator (RFC 8707) mediante el campo resource.
|
|
180
237
|
*/
|
|
181
|
-
getLoginUrl(options?:
|
|
182
|
-
state?: string;
|
|
183
|
-
scopes?: string[];
|
|
184
|
-
}): Promise<LoginUrlResult>;
|
|
238
|
+
getLoginUrl(options?: AuthorizationUrlOptions): Promise<LoginUrlResult>;
|
|
185
239
|
/**
|
|
186
240
|
* Abre una ventana emergente para inicio de sesión OAuth y devuelve tokens al completarse.
|
|
187
241
|
*
|
|
@@ -203,7 +257,13 @@ declare class OAuthService {
|
|
|
203
257
|
*/
|
|
204
258
|
handleCallback(code: string, codeVerifier?: string, callbackState?: string): Promise<OAuthTokens>;
|
|
205
259
|
/**
|
|
206
|
-
* Refresca el token de acceso usando el refresh_token
|
|
260
|
+
* Refresca el token de acceso usando el refresh_token.
|
|
261
|
+
*
|
|
262
|
+
* Deduplica peticiones concurrentes mediante una promesa cacheada: si dos
|
|
263
|
+
* llamadas entran a la vez, comparten la misma petición HTTP. Esto es
|
|
264
|
+
* imprescindible porque el backend implementa rotación de refresh tokens con
|
|
265
|
+
* detección de reuso; dos refresh concurrentes con el mismo token producirían
|
|
266
|
+
* una invalidación inmediata de toda la cadena.
|
|
207
267
|
*
|
|
208
268
|
* @returns Nuevos tokens OAuth
|
|
209
269
|
* @throws Error si no hay refresh_token disponible
|
|
@@ -216,12 +276,39 @@ declare class OAuthService {
|
|
|
216
276
|
*/
|
|
217
277
|
getUserInfo(): Promise<OAuthUserInfo>;
|
|
218
278
|
/**
|
|
219
|
-
* Revoca el token actual
|
|
279
|
+
* Revoca el token actual almacenado y limpia el storage.
|
|
220
280
|
*
|
|
221
|
-
* @param tokenType - Tipo de token a revocar (
|
|
281
|
+
* @param tokenType - Tipo de token a revocar (`access_token` o `refresh_token`).
|
|
222
282
|
* Por defecto revoca el access_token.
|
|
223
283
|
*/
|
|
224
284
|
revokeToken(tokenType?: 'access_token' | 'refresh_token'): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Revoca un token arbitrario contra el endpoint `/oauth/revoke` (RFC 7009).
|
|
287
|
+
* A diferencia de `revokeToken()`, no toca el almacenamiento local.
|
|
288
|
+
*
|
|
289
|
+
* @param token - Token a revocar (access token o refresh token).
|
|
290
|
+
* @param tokenTypeHint - Pista opcional sobre el tipo de token.
|
|
291
|
+
*/
|
|
292
|
+
revoke(token: string, tokenTypeHint?: 'access_token' | 'refresh_token'): Promise<void>;
|
|
293
|
+
/**
|
|
294
|
+
* Introspecciona un token contra `/oauth/introspect` (RFC 7662).
|
|
295
|
+
* Requiere que el cliente esté autenticado (client_secret o public con PKCE).
|
|
296
|
+
*
|
|
297
|
+
* @param token - Token a introspeccionar.
|
|
298
|
+
* @param tokenTypeHint - Pista opcional sobre el tipo de token.
|
|
299
|
+
* @returns Estado y metadatos del token.
|
|
300
|
+
*/
|
|
301
|
+
introspect(token: string, tokenTypeHint?: 'access_token' | 'refresh_token'): Promise<IntrospectResponse>;
|
|
302
|
+
/**
|
|
303
|
+
* Lista las aplicaciones OAuth autorizadas por el usuario actual.
|
|
304
|
+
* Requiere un access token válido.
|
|
305
|
+
*/
|
|
306
|
+
getAuthorizedApps(): Promise<AuthorizedApp[]>;
|
|
307
|
+
/**
|
|
308
|
+
* Revoca el acceso de una aplicación OAuth concreta del usuario actual.
|
|
309
|
+
* Todos los tokens emitidos para esa aplicación quedan invalidados.
|
|
310
|
+
*/
|
|
311
|
+
revokeApp(clientId: string): Promise<void>;
|
|
225
312
|
/**
|
|
226
313
|
* Obtiene un access token válido, refrescándolo automáticamente si ha expirado
|
|
227
314
|
*
|
|
@@ -731,6 +818,877 @@ interface ErrorStats {
|
|
|
731
818
|
}>;
|
|
732
819
|
}
|
|
733
820
|
|
|
821
|
+
/**
|
|
822
|
+
* Tipos relacionados con presupuestos (CRM Budgets)
|
|
823
|
+
*
|
|
824
|
+
* Expuestos por la API REST bajo `/api/crm/budgets` y `/api/crm/budget-templates`.
|
|
825
|
+
*/
|
|
826
|
+
|
|
827
|
+
/** Estado del presupuesto. */
|
|
828
|
+
type BudgetStatus = 'DRAFT' | 'SENT' | 'APPROVED' | 'REJECTED' | 'EXPIRED' | 'CANCELLED';
|
|
829
|
+
/** Tipo de linea en el presupuesto. */
|
|
830
|
+
type BudgetItemType = 'ITEM' | 'SERVICE' | 'SECTION_HEADER';
|
|
831
|
+
/** Tipo semantico de seccion. */
|
|
832
|
+
type BudgetSectionType = 'INTRO' | 'INFO' | 'SCOPE' | 'TIMELINE' | 'COSTS' | 'PAYMENT' | 'CUSTOM' | 'RICH_HTML';
|
|
833
|
+
/** Posicion de la seccion respecto a la tabla de items. */
|
|
834
|
+
type BudgetSectionPosition = 'BEFORE_ITEMS' | 'AFTER_ITEMS';
|
|
835
|
+
/** Metodo de pago propuesto. */
|
|
836
|
+
type PaymentMethod = 'TRANSFER' | 'CASH' | 'CARD' | 'CHECK' | 'OTHER';
|
|
837
|
+
/** Quien aprueba o rechaza un presupuesto. */
|
|
838
|
+
type ApproverType = 'INTERNAL' | 'CLIENT';
|
|
839
|
+
/** Operaciones soportadas por el endpoint de masivos. */
|
|
840
|
+
type BulkBudgetOperation = 'delete' | 'cancel' | 'change-status';
|
|
841
|
+
/** Orden ascendente o descendente. */
|
|
842
|
+
type SortOrder = 'asc' | 'desc';
|
|
843
|
+
/** DTO para anyadir un item al presupuesto. */
|
|
844
|
+
interface CreateBudgetItemInput {
|
|
845
|
+
/** UUID opcional. Se genera si no se indica. */
|
|
846
|
+
id?: string;
|
|
847
|
+
/** Tipo de linea. Por defecto ITEM. */
|
|
848
|
+
type?: BudgetItemType;
|
|
849
|
+
/** Nombre visible en el PDF. */
|
|
850
|
+
name: string;
|
|
851
|
+
/** Descripcion detallada (acepta texto plano). */
|
|
852
|
+
description?: string;
|
|
853
|
+
/** Codigo interno del item. */
|
|
854
|
+
code?: string;
|
|
855
|
+
/** Cantidad (por defecto 1). */
|
|
856
|
+
quantity: number;
|
|
857
|
+
/** Precio unitario sin impuestos. */
|
|
858
|
+
unitPrice: number;
|
|
859
|
+
/** Descuento aplicado al item en porcentaje (0-100). */
|
|
860
|
+
discount?: number;
|
|
861
|
+
/** Tasa impositiva del item en porcentaje (IVA/IGIC). */
|
|
862
|
+
taxRate?: number;
|
|
863
|
+
/** Coste interno (no visible para el cliente). */
|
|
864
|
+
internalCost?: number;
|
|
865
|
+
/** Orden de aparicion. */
|
|
866
|
+
order?: number;
|
|
867
|
+
/** Metadatos adicionales. */
|
|
868
|
+
metadata?: Record<string, unknown>;
|
|
869
|
+
}
|
|
870
|
+
/** DTO parcial para actualizar un item existente. */
|
|
871
|
+
type UpdateBudgetItemInput = Partial<Omit<CreateBudgetItemInput, 'id'>>;
|
|
872
|
+
/** Item de presupuesto devuelto por la API. */
|
|
873
|
+
interface BudgetItem {
|
|
874
|
+
id: string;
|
|
875
|
+
budgetId: string;
|
|
876
|
+
type: BudgetItemType;
|
|
877
|
+
name: string;
|
|
878
|
+
description?: string | null;
|
|
879
|
+
code?: string | null;
|
|
880
|
+
quantity: number;
|
|
881
|
+
unitPrice: number;
|
|
882
|
+
discount: number;
|
|
883
|
+
taxRate: number;
|
|
884
|
+
/** Subtotal calculado: quantity * unitPrice - descuento. */
|
|
885
|
+
subtotal: number;
|
|
886
|
+
/** Coste interno; solo presente si el usuario tiene permiso. */
|
|
887
|
+
internalCost?: number | null;
|
|
888
|
+
order: number;
|
|
889
|
+
metadata?: Record<string, unknown> | null;
|
|
890
|
+
createdAt: string;
|
|
891
|
+
updatedAt: string;
|
|
892
|
+
}
|
|
893
|
+
/** Pareja id + order para reordenar items. */
|
|
894
|
+
interface BudgetItemOrder {
|
|
895
|
+
id: string;
|
|
896
|
+
order: number;
|
|
897
|
+
}
|
|
898
|
+
interface ReorderItemsInput {
|
|
899
|
+
items: BudgetItemOrder[];
|
|
900
|
+
}
|
|
901
|
+
/** DTO para anyadir una seccion al presupuesto. */
|
|
902
|
+
interface CreateBudgetSectionInput {
|
|
903
|
+
id?: string;
|
|
904
|
+
/** Tipo semantico. Por defecto CUSTOM. */
|
|
905
|
+
type?: BudgetSectionType;
|
|
906
|
+
/** Posicion respecto a los items. Por defecto BEFORE_ITEMS. */
|
|
907
|
+
position?: BudgetSectionPosition;
|
|
908
|
+
/** Titulo visible de la seccion. */
|
|
909
|
+
title: string;
|
|
910
|
+
/** Contenido HTML/Markdown. En RICH_HTML se renderiza como imagen en el PDF. */
|
|
911
|
+
content?: string;
|
|
912
|
+
order?: number;
|
|
913
|
+
metadata?: Record<string, unknown>;
|
|
914
|
+
}
|
|
915
|
+
type UpdateBudgetSectionInput = Partial<Omit<CreateBudgetSectionInput, 'id'>>;
|
|
916
|
+
interface BudgetSection {
|
|
917
|
+
id: string;
|
|
918
|
+
budgetId: string;
|
|
919
|
+
type: BudgetSectionType;
|
|
920
|
+
position: BudgetSectionPosition;
|
|
921
|
+
title: string;
|
|
922
|
+
content?: string | null;
|
|
923
|
+
order: number;
|
|
924
|
+
metadata?: Record<string, unknown> | null;
|
|
925
|
+
createdAt: string;
|
|
926
|
+
updatedAt: string;
|
|
927
|
+
}
|
|
928
|
+
interface ReorderSectionsInput {
|
|
929
|
+
/** UUIDs de las secciones en el nuevo orden deseado. */
|
|
930
|
+
sectionIds: string[];
|
|
931
|
+
}
|
|
932
|
+
interface BudgetApproval {
|
|
933
|
+
id: string;
|
|
934
|
+
budgetId: string;
|
|
935
|
+
action: 'APPROVED' | 'REJECTED';
|
|
936
|
+
approverType: ApproverType;
|
|
937
|
+
approverId?: string | null;
|
|
938
|
+
approverName?: string | null;
|
|
939
|
+
approverEmail?: string | null;
|
|
940
|
+
reason?: string | null;
|
|
941
|
+
comments?: string | null;
|
|
942
|
+
createdAt: string;
|
|
943
|
+
}
|
|
944
|
+
interface BudgetAttachment {
|
|
945
|
+
id: string;
|
|
946
|
+
budgetId: string;
|
|
947
|
+
fileId: string;
|
|
948
|
+
name: string;
|
|
949
|
+
description?: string | null;
|
|
950
|
+
mimeType: string;
|
|
951
|
+
size: number;
|
|
952
|
+
url?: string;
|
|
953
|
+
uploadedById: string;
|
|
954
|
+
createdAt: string;
|
|
955
|
+
}
|
|
956
|
+
/** Cliente relacionado (subconjunto expuesto en presupuestos). */
|
|
957
|
+
interface BudgetClientRef {
|
|
958
|
+
id: string;
|
|
959
|
+
name: string;
|
|
960
|
+
email?: string | null;
|
|
961
|
+
taxId?: string | null;
|
|
962
|
+
}
|
|
963
|
+
interface BudgetProjectRef {
|
|
964
|
+
id: string;
|
|
965
|
+
name: string;
|
|
966
|
+
}
|
|
967
|
+
interface BudgetOpportunityRef {
|
|
968
|
+
id: string;
|
|
969
|
+
title: string;
|
|
970
|
+
}
|
|
971
|
+
interface BudgetUserRef {
|
|
972
|
+
id: string;
|
|
973
|
+
name: string;
|
|
974
|
+
email?: string | null;
|
|
975
|
+
}
|
|
976
|
+
/** Listado de presupuesto (version resumida). */
|
|
977
|
+
interface BudgetListItem {
|
|
978
|
+
id: string;
|
|
979
|
+
code: string;
|
|
980
|
+
title: string;
|
|
981
|
+
status: BudgetStatus;
|
|
982
|
+
currency: string;
|
|
983
|
+
issueDate: string;
|
|
984
|
+
validUntil: string;
|
|
985
|
+
total: number;
|
|
986
|
+
version: number;
|
|
987
|
+
tags: string[];
|
|
988
|
+
client?: BudgetClientRef | null;
|
|
989
|
+
project?: BudgetProjectRef | null;
|
|
990
|
+
opportunity?: BudgetOpportunityRef | null;
|
|
991
|
+
createdBy?: BudgetUserRef | null;
|
|
992
|
+
createdAt: string;
|
|
993
|
+
updatedAt: string;
|
|
994
|
+
}
|
|
995
|
+
/** Presupuesto completo con items, secciones y aprobaciones. */
|
|
996
|
+
interface Budget extends BudgetListItem {
|
|
997
|
+
description?: string | null;
|
|
998
|
+
taxRate: number;
|
|
999
|
+
discount: number;
|
|
1000
|
+
discountPercent: number;
|
|
1001
|
+
subtotal: number;
|
|
1002
|
+
taxAmount: number;
|
|
1003
|
+
internalCost?: number | null;
|
|
1004
|
+
profit?: number | null;
|
|
1005
|
+
profitMargin?: number | null;
|
|
1006
|
+
paymentMethod?: PaymentMethod | null;
|
|
1007
|
+
paymentTerms?: string | null;
|
|
1008
|
+
termsAndConditions?: string | null;
|
|
1009
|
+
notes?: string | null;
|
|
1010
|
+
includeAcceptanceSection: boolean;
|
|
1011
|
+
metadata?: Record<string, unknown> | null;
|
|
1012
|
+
items: BudgetItem[];
|
|
1013
|
+
sections: BudgetSection[];
|
|
1014
|
+
approvals?: BudgetApproval[];
|
|
1015
|
+
attachments?: BudgetAttachment[];
|
|
1016
|
+
previousVersionId?: string | null;
|
|
1017
|
+
nextVersionId?: string | null;
|
|
1018
|
+
}
|
|
1019
|
+
interface CreateBudgetInput {
|
|
1020
|
+
/** Codigo. Si se omite, se autogenera segun la configuracion. */
|
|
1021
|
+
code?: string;
|
|
1022
|
+
/** Codigo ISO 4217 de la moneda (3 letras mayus). */
|
|
1023
|
+
currency?: string;
|
|
1024
|
+
/** Titulo visible para el cliente. */
|
|
1025
|
+
title: string;
|
|
1026
|
+
/** Descripcion general. */
|
|
1027
|
+
description?: string;
|
|
1028
|
+
/** UUID del cliente destinatario. */
|
|
1029
|
+
clientId: string;
|
|
1030
|
+
/** UUID del proyecto CRM asociado. */
|
|
1031
|
+
projectId?: string;
|
|
1032
|
+
/** UUID de la oportunidad comercial asociada. */
|
|
1033
|
+
opportunityId?: string;
|
|
1034
|
+
/** Fecha de emision (ISO 8601). Por defecto hoy. */
|
|
1035
|
+
issueDate?: string;
|
|
1036
|
+
/** Fecha de validez (ISO 8601). Obligatoria. */
|
|
1037
|
+
validUntil: string;
|
|
1038
|
+
/** Tasa impositiva global (0-100). */
|
|
1039
|
+
taxRate?: number;
|
|
1040
|
+
/** Descuento absoluto. */
|
|
1041
|
+
discount?: number;
|
|
1042
|
+
/** Descuento porcentual (0-100). */
|
|
1043
|
+
discountPercent?: number;
|
|
1044
|
+
/** Coste interno global (no visible al cliente). */
|
|
1045
|
+
internalCost?: number;
|
|
1046
|
+
/** Metodo de pago propuesto. */
|
|
1047
|
+
paymentMethod?: PaymentMethod;
|
|
1048
|
+
/** Condiciones de pago en texto libre. */
|
|
1049
|
+
paymentTerms?: string;
|
|
1050
|
+
/** Terminos y condiciones. Acepta Markdown. */
|
|
1051
|
+
termsAndConditions?: string;
|
|
1052
|
+
/** Notas internas. */
|
|
1053
|
+
notes?: string;
|
|
1054
|
+
/** Incluir seccion de aceptacion en el PDF generado. */
|
|
1055
|
+
includeAcceptanceSection?: boolean;
|
|
1056
|
+
/** Etiquetas para categorizar. */
|
|
1057
|
+
tags?: string[];
|
|
1058
|
+
/** Metadatos adicionales. */
|
|
1059
|
+
metadata?: Record<string, unknown>;
|
|
1060
|
+
/** Estado inicial. Por defecto DRAFT. */
|
|
1061
|
+
status?: BudgetStatus;
|
|
1062
|
+
/** Lista de items a crear junto al presupuesto. */
|
|
1063
|
+
items?: CreateBudgetItemInput[];
|
|
1064
|
+
/** Lista de secciones a crear junto al presupuesto. */
|
|
1065
|
+
sections?: CreateBudgetSectionInput[];
|
|
1066
|
+
}
|
|
1067
|
+
type UpdateBudgetInput = Partial<Omit<CreateBudgetInput, 'clientId'>> & {
|
|
1068
|
+
clientId?: string;
|
|
1069
|
+
};
|
|
1070
|
+
/** Filtros para listar presupuestos. */
|
|
1071
|
+
interface BudgetFilters {
|
|
1072
|
+
page?: number;
|
|
1073
|
+
limit?: number;
|
|
1074
|
+
/** Busqueda libre por codigo, titulo o descripcion. */
|
|
1075
|
+
search?: string;
|
|
1076
|
+
/** Uno o varios estados. */
|
|
1077
|
+
status?: BudgetStatus | BudgetStatus[];
|
|
1078
|
+
clientId?: string;
|
|
1079
|
+
projectId?: string;
|
|
1080
|
+
opportunityId?: string;
|
|
1081
|
+
createdById?: string;
|
|
1082
|
+
version?: number;
|
|
1083
|
+
/** Rango de fechas de emision. */
|
|
1084
|
+
fromDate?: string;
|
|
1085
|
+
toDate?: string;
|
|
1086
|
+
/** Rango de fechas de validez. */
|
|
1087
|
+
validFromDate?: string;
|
|
1088
|
+
validToDate?: string;
|
|
1089
|
+
/** Rango de importes. */
|
|
1090
|
+
minAmount?: number;
|
|
1091
|
+
maxAmount?: number;
|
|
1092
|
+
tags?: string[];
|
|
1093
|
+
sortBy?: string;
|
|
1094
|
+
sortOrder?: SortOrder;
|
|
1095
|
+
}
|
|
1096
|
+
interface BudgetListResponse {
|
|
1097
|
+
data: BudgetListItem[];
|
|
1098
|
+
pagination: PaginationMeta;
|
|
1099
|
+
}
|
|
1100
|
+
interface SendBudgetInput {
|
|
1101
|
+
/** Destinatarios principales (To). */
|
|
1102
|
+
emails: string[];
|
|
1103
|
+
/** Asunto del correo. */
|
|
1104
|
+
subject?: string;
|
|
1105
|
+
/** Mensaje personalizado en el cuerpo. */
|
|
1106
|
+
message?: string;
|
|
1107
|
+
/** Direcciones CC. */
|
|
1108
|
+
cc?: string[];
|
|
1109
|
+
/** Direcciones BCC. */
|
|
1110
|
+
bcc?: string[];
|
|
1111
|
+
/** Incluir adjuntos del presupuesto ademas del PDF. */
|
|
1112
|
+
includeAttachments?: boolean;
|
|
1113
|
+
}
|
|
1114
|
+
interface ApproveBudgetInput {
|
|
1115
|
+
/** Comentarios adicionales. */
|
|
1116
|
+
comments?: string;
|
|
1117
|
+
/** Crear automaticamente un proyecto. */
|
|
1118
|
+
createProject?: boolean;
|
|
1119
|
+
/** Quien aprueba. */
|
|
1120
|
+
approverType?: ApproverType;
|
|
1121
|
+
/** Nombre del contacto del cliente que aprueba (si approverType es CLIENT). */
|
|
1122
|
+
clientApproverName?: string;
|
|
1123
|
+
/** Correo del contacto del cliente que aprueba. */
|
|
1124
|
+
clientApproverEmail?: string;
|
|
1125
|
+
}
|
|
1126
|
+
interface RejectBudgetInput {
|
|
1127
|
+
/** Motivo del rechazo. Obligatorio. */
|
|
1128
|
+
reason: string;
|
|
1129
|
+
/** Comentarios adicionales. */
|
|
1130
|
+
comments?: string;
|
|
1131
|
+
approverType?: ApproverType;
|
|
1132
|
+
clientApproverName?: string;
|
|
1133
|
+
clientApproverEmail?: string;
|
|
1134
|
+
}
|
|
1135
|
+
interface ChangeStatusInput {
|
|
1136
|
+
status: BudgetStatus;
|
|
1137
|
+
reason?: string;
|
|
1138
|
+
}
|
|
1139
|
+
interface ConvertToProjectInput {
|
|
1140
|
+
name: string;
|
|
1141
|
+
startDate: string;
|
|
1142
|
+
estimatedEndDate?: string;
|
|
1143
|
+
description?: string;
|
|
1144
|
+
/** Convertir items en tareas (por defecto true). */
|
|
1145
|
+
copyItemsAsTasks?: boolean;
|
|
1146
|
+
}
|
|
1147
|
+
interface ConvertToInvoiceInput {
|
|
1148
|
+
/** Emitir la factura directamente (ISSUED) en lugar de DRAFT. */
|
|
1149
|
+
issueDirectly?: boolean;
|
|
1150
|
+
/** Metodo de pago (hereda si se omite). */
|
|
1151
|
+
paymentMethod?: PaymentMethod;
|
|
1152
|
+
/** Condiciones de pago (hereda si se omite). */
|
|
1153
|
+
paymentTerms?: string;
|
|
1154
|
+
/** Fecha de vencimiento. */
|
|
1155
|
+
dueDate?: string;
|
|
1156
|
+
/** Notas visibles. */
|
|
1157
|
+
notes?: string;
|
|
1158
|
+
/** Notas internas no visibles para el cliente. */
|
|
1159
|
+
internalNotes?: string;
|
|
1160
|
+
}
|
|
1161
|
+
interface DuplicateBudgetInput {
|
|
1162
|
+
/** Cliente destino. Si se omite, conserva el del original. */
|
|
1163
|
+
targetClientId?: string;
|
|
1164
|
+
/** Titulo del duplicado. */
|
|
1165
|
+
title?: string;
|
|
1166
|
+
/** Resetear a DRAFT (por defecto true). */
|
|
1167
|
+
resetStatus?: boolean;
|
|
1168
|
+
/** Copiar registros de adjuntos. */
|
|
1169
|
+
includeAttachments?: boolean;
|
|
1170
|
+
}
|
|
1171
|
+
interface BulkBudgetOptions {
|
|
1172
|
+
/** Nuevo estado (obligatorio cuando la operacion es change-status). */
|
|
1173
|
+
newStatus?: BudgetStatus;
|
|
1174
|
+
}
|
|
1175
|
+
interface BulkBudgetInput {
|
|
1176
|
+
operation: BulkBudgetOperation;
|
|
1177
|
+
ids: string[];
|
|
1178
|
+
options?: BulkBudgetOptions;
|
|
1179
|
+
}
|
|
1180
|
+
interface BulkBudgetResultItem {
|
|
1181
|
+
id: string;
|
|
1182
|
+
success: boolean;
|
|
1183
|
+
error?: string;
|
|
1184
|
+
}
|
|
1185
|
+
interface BulkBudgetResult {
|
|
1186
|
+
success: number;
|
|
1187
|
+
failed: number;
|
|
1188
|
+
results: BulkBudgetResultItem[];
|
|
1189
|
+
}
|
|
1190
|
+
interface BudgetHistoryEntry {
|
|
1191
|
+
id: string;
|
|
1192
|
+
budgetId: string;
|
|
1193
|
+
version: number;
|
|
1194
|
+
action: string;
|
|
1195
|
+
actorId?: string | null;
|
|
1196
|
+
actorName?: string | null;
|
|
1197
|
+
changes?: Record<string, unknown> | null;
|
|
1198
|
+
createdAt: string;
|
|
1199
|
+
}
|
|
1200
|
+
interface NextCodeResponse {
|
|
1201
|
+
code: string;
|
|
1202
|
+
}
|
|
1203
|
+
interface CheckCodeResponse {
|
|
1204
|
+
exists: boolean;
|
|
1205
|
+
}
|
|
1206
|
+
interface BudgetPdfUrlResponse {
|
|
1207
|
+
url: string;
|
|
1208
|
+
}
|
|
1209
|
+
interface UploadedBudgetImage {
|
|
1210
|
+
url: string;
|
|
1211
|
+
}
|
|
1212
|
+
interface GenerateItemsAiInput {
|
|
1213
|
+
/** Texto en lenguaje natural (minimo 10 caracteres). */
|
|
1214
|
+
text: string;
|
|
1215
|
+
}
|
|
1216
|
+
interface AiGeneratedItem {
|
|
1217
|
+
name: string;
|
|
1218
|
+
description?: string;
|
|
1219
|
+
quantity: number;
|
|
1220
|
+
unitPrice: number;
|
|
1221
|
+
taxRate?: number;
|
|
1222
|
+
type?: BudgetItemType;
|
|
1223
|
+
}
|
|
1224
|
+
interface AiGeneratedSection {
|
|
1225
|
+
type: BudgetSectionType;
|
|
1226
|
+
position: BudgetSectionPosition;
|
|
1227
|
+
title: string;
|
|
1228
|
+
content: string;
|
|
1229
|
+
}
|
|
1230
|
+
interface GenerateItemsAiJob {
|
|
1231
|
+
jobId: string;
|
|
1232
|
+
}
|
|
1233
|
+
interface GenerateCompleteAiResult {
|
|
1234
|
+
sections: AiGeneratedSection[];
|
|
1235
|
+
items: AiGeneratedItem[];
|
|
1236
|
+
suggestedTitle?: string;
|
|
1237
|
+
suggestedPaymentTerms?: string;
|
|
1238
|
+
suggestedTermsAndConditions?: string;
|
|
1239
|
+
}
|
|
1240
|
+
interface GenerateSectionsAiResult {
|
|
1241
|
+
sections: AiGeneratedSection[];
|
|
1242
|
+
}
|
|
1243
|
+
type BudgetExportFormat = 'csv';
|
|
1244
|
+
/**
|
|
1245
|
+
* Eventos de webhook emitidos por el modulo de presupuestos.
|
|
1246
|
+
* Formato UPPER_SNAKE coherente con el resto de eventos de la plataforma.
|
|
1247
|
+
*/
|
|
1248
|
+
type BudgetWebhookEvent = 'BUDGET_CREATED' | 'BUDGET_UPDATED' | 'BUDGET_SENT' | 'BUDGET_APPROVED' | 'BUDGET_REJECTED' | 'BUDGET_CANCELLED' | 'BUDGET_EXPIRED' | 'BUDGET_DUPLICATED' | 'BUDGET_CONVERTED_TO_PROJECT' | 'BUDGET_CONVERTED_TO_INVOICE';
|
|
1249
|
+
/**
|
|
1250
|
+
* Lista completa de eventos de webhook de presupuestos.
|
|
1251
|
+
* Util para registrar todos los eventos al configurar una app externa.
|
|
1252
|
+
*/
|
|
1253
|
+
declare const BUDGET_WEBHOOK_EVENTS: readonly BudgetWebhookEvent[];
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* Tipos relacionados con plantillas de presupuesto.
|
|
1257
|
+
*
|
|
1258
|
+
* Expuestos por la API REST bajo `/api/crm/budget-templates`.
|
|
1259
|
+
*/
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Estructura sugerida de una seccion dentro de `sectionsJson` de la plantilla.
|
|
1263
|
+
* El backend acepta `unknown[]` pero esta es la estructura recomendada.
|
|
1264
|
+
*/
|
|
1265
|
+
interface BudgetTemplateSectionJson {
|
|
1266
|
+
type: BudgetSectionType;
|
|
1267
|
+
position: BudgetSectionPosition;
|
|
1268
|
+
title: string;
|
|
1269
|
+
content?: string;
|
|
1270
|
+
order?: number;
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Estructura sugerida de un item dentro de `itemsJson` de la plantilla.
|
|
1274
|
+
*/
|
|
1275
|
+
interface BudgetTemplateItemJson {
|
|
1276
|
+
type?: BudgetItemType;
|
|
1277
|
+
name: string;
|
|
1278
|
+
description?: string;
|
|
1279
|
+
code?: string;
|
|
1280
|
+
quantity: number;
|
|
1281
|
+
unitPrice: number;
|
|
1282
|
+
taxRate?: number;
|
|
1283
|
+
discount?: number;
|
|
1284
|
+
order?: number;
|
|
1285
|
+
}
|
|
1286
|
+
/** Plantilla de presupuesto. */
|
|
1287
|
+
interface BudgetTemplate {
|
|
1288
|
+
id: string;
|
|
1289
|
+
name: string;
|
|
1290
|
+
description?: string | null;
|
|
1291
|
+
icon?: string | null;
|
|
1292
|
+
defaultTitle?: string | null;
|
|
1293
|
+
defaultValidDays?: number | null;
|
|
1294
|
+
defaultTaxRate?: number | null;
|
|
1295
|
+
defaultPaymentTerms?: string | null;
|
|
1296
|
+
defaultTermsAndConditions?: string | null;
|
|
1297
|
+
includeAcceptanceSection: boolean;
|
|
1298
|
+
/** Secciones de la plantilla. */
|
|
1299
|
+
sectionsJson: BudgetTemplateSectionJson[];
|
|
1300
|
+
/** Items de la plantilla. */
|
|
1301
|
+
itemsJson: BudgetTemplateItemJson[];
|
|
1302
|
+
/** Plantilla del sistema (inmutable). */
|
|
1303
|
+
isSystemDefault: boolean;
|
|
1304
|
+
/** Activa / archivada. */
|
|
1305
|
+
isActive: boolean;
|
|
1306
|
+
createdById?: string | null;
|
|
1307
|
+
createdAt: string;
|
|
1308
|
+
updatedAt: string;
|
|
1309
|
+
}
|
|
1310
|
+
/** DTO para crear una plantilla personalizada. */
|
|
1311
|
+
interface CreateBudgetTemplateInput {
|
|
1312
|
+
name: string;
|
|
1313
|
+
description?: string;
|
|
1314
|
+
icon?: string;
|
|
1315
|
+
defaultTitle?: string;
|
|
1316
|
+
defaultValidDays?: number;
|
|
1317
|
+
defaultTaxRate?: number;
|
|
1318
|
+
defaultPaymentTerms?: string;
|
|
1319
|
+
defaultTermsAndConditions?: string;
|
|
1320
|
+
includeAcceptanceSection?: boolean;
|
|
1321
|
+
sectionsJson?: BudgetTemplateSectionJson[];
|
|
1322
|
+
itemsJson?: BudgetTemplateItemJson[];
|
|
1323
|
+
}
|
|
1324
|
+
/** DTO parcial para actualizar una plantilla. */
|
|
1325
|
+
type UpdateBudgetTemplateInput = Partial<CreateBudgetTemplateInput>;
|
|
1326
|
+
/** DTO para guardar un presupuesto existente como plantilla. */
|
|
1327
|
+
interface CreateTemplateFromBudgetInput {
|
|
1328
|
+
name: string;
|
|
1329
|
+
description?: string;
|
|
1330
|
+
icon?: string;
|
|
1331
|
+
}
|
|
1332
|
+
/** DTO para crear un presupuesto aplicando una plantilla. */
|
|
1333
|
+
interface ApplyTemplateInput {
|
|
1334
|
+
clientId: string;
|
|
1335
|
+
opportunityId?: string;
|
|
1336
|
+
/** Titulo personalizado. Si se omite, se usa `defaultTitle` de la plantilla. */
|
|
1337
|
+
title?: string;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Tipos del servicio de comentarios de presupuesto.
|
|
1342
|
+
*
|
|
1343
|
+
* Los comentarios soportan dos visibilidades:
|
|
1344
|
+
* - `INTERNAL`: solo visible para el equipo.
|
|
1345
|
+
* - `CLIENT`: visible también en el portal del cliente.
|
|
1346
|
+
*
|
|
1347
|
+
* Un comentario puede provenir de un usuario interno (`authorKind = 'INTERNAL'`)
|
|
1348
|
+
* o de un usuario del portal cliente (`authorKind = 'PORTAL'`). La autoría es
|
|
1349
|
+
* exclusiva: exactamente uno de `authorId` / `portalAuthorId` está presente.
|
|
1350
|
+
*/
|
|
1351
|
+
/** Visibilidades admitidas para un comentario. */
|
|
1352
|
+
type BudgetCommentVisibility = 'INTERNAL' | 'CLIENT';
|
|
1353
|
+
/** Origen de la autoría del comentario. */
|
|
1354
|
+
type BudgetCommentAuthorKind = 'INTERNAL' | 'PORTAL';
|
|
1355
|
+
/** Datos del autor interno cuando el comentario lo escribe un usuario del equipo. */
|
|
1356
|
+
interface BudgetCommentAuthor {
|
|
1357
|
+
id: string;
|
|
1358
|
+
firstName?: string | null;
|
|
1359
|
+
lastName?: string | null;
|
|
1360
|
+
avatar?: string | null;
|
|
1361
|
+
}
|
|
1362
|
+
/** Datos del autor desde el portal cliente. */
|
|
1363
|
+
interface BudgetCommentPortalAuthor {
|
|
1364
|
+
id: string;
|
|
1365
|
+
firstName?: string | null;
|
|
1366
|
+
lastName?: string | null;
|
|
1367
|
+
avatarUrl?: string | null;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Comentario de presupuesto. El `body` puede venir como string plano o como
|
|
1371
|
+
* objeto con versión Markdown y plain text (según cómo lo serialice el
|
|
1372
|
+
* backend).
|
|
1373
|
+
*/
|
|
1374
|
+
interface BudgetComment {
|
|
1375
|
+
id: string;
|
|
1376
|
+
budgetId: string;
|
|
1377
|
+
authorId?: string | null;
|
|
1378
|
+
author?: BudgetCommentAuthor | null;
|
|
1379
|
+
portalAuthorId?: string | null;
|
|
1380
|
+
portalAuthor?: BudgetCommentPortalAuthor | null;
|
|
1381
|
+
authorKind?: BudgetCommentAuthorKind;
|
|
1382
|
+
visibility: BudgetCommentVisibility;
|
|
1383
|
+
body: string | {
|
|
1384
|
+
markdown: string;
|
|
1385
|
+
plainText: string;
|
|
1386
|
+
};
|
|
1387
|
+
mentionedUserIds?: string[];
|
|
1388
|
+
createdAt: string;
|
|
1389
|
+
editedAt?: string | null;
|
|
1390
|
+
updatedAt?: string;
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Entrada para crear un comentario.
|
|
1394
|
+
*
|
|
1395
|
+
* Si se envía `clientOperationId`, el backend puede deduplicar la operación
|
|
1396
|
+
* en batch (ver `bulkCreate`).
|
|
1397
|
+
*/
|
|
1398
|
+
interface CreateBudgetCommentInput {
|
|
1399
|
+
body: string;
|
|
1400
|
+
visibility?: BudgetCommentVisibility;
|
|
1401
|
+
mentionedUserIds?: string[];
|
|
1402
|
+
clientOperationId?: string;
|
|
1403
|
+
}
|
|
1404
|
+
/** Entrada para editar un comentario existente. */
|
|
1405
|
+
interface UpdateBudgetCommentInput {
|
|
1406
|
+
body: string;
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* Filtros para listar comentarios. `ALL` es azúcar local del SDK: se mapea a
|
|
1410
|
+
* "sin filtro de visibilidad" en el query.
|
|
1411
|
+
*/
|
|
1412
|
+
interface ListBudgetCommentsFilter {
|
|
1413
|
+
visibility?: BudgetCommentVisibility | 'ALL';
|
|
1414
|
+
authorId?: string;
|
|
1415
|
+
mentionedUserId?: string;
|
|
1416
|
+
cursor?: string;
|
|
1417
|
+
limit?: number;
|
|
1418
|
+
since?: string;
|
|
1419
|
+
until?: string;
|
|
1420
|
+
/** Número de página (1-indexado) cuando el endpoint usa paginación offset. */
|
|
1421
|
+
page?: number;
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Información de paginación del listado de comentarios.
|
|
1425
|
+
*
|
|
1426
|
+
* El backend actual devuelve paginación offset (`page`, `limit`, `total`,
|
|
1427
|
+
* `totalPages`). Se conservan también los campos por cursor para compatibilidad
|
|
1428
|
+
* futura si el servicio migrara a paginación por cursor.
|
|
1429
|
+
*/
|
|
1430
|
+
interface BudgetCommentPageInfo {
|
|
1431
|
+
page?: number;
|
|
1432
|
+
limit?: number;
|
|
1433
|
+
total?: number;
|
|
1434
|
+
totalPages?: number;
|
|
1435
|
+
nextCursor?: string | null;
|
|
1436
|
+
hasMore?: boolean;
|
|
1437
|
+
pageSize?: number;
|
|
1438
|
+
}
|
|
1439
|
+
/** Respuesta paginada del listado de comentarios. */
|
|
1440
|
+
interface BudgetCommentListResponse {
|
|
1441
|
+
data: BudgetComment[];
|
|
1442
|
+
pageInfo: BudgetCommentPageInfo;
|
|
1443
|
+
}
|
|
1444
|
+
/** Detalle de un fallo individual en una operación batch. */
|
|
1445
|
+
interface BudgetCommentBulkFailure {
|
|
1446
|
+
index: number;
|
|
1447
|
+
clientOperationId?: string;
|
|
1448
|
+
code: string;
|
|
1449
|
+
message: string;
|
|
1450
|
+
}
|
|
1451
|
+
/** Resultado de `bulkCreate` en modo saga (tolerante a fallos parciales). */
|
|
1452
|
+
interface BudgetCommentBulkResult {
|
|
1453
|
+
succeeded: BudgetComment[];
|
|
1454
|
+
failed: BudgetCommentBulkFailure[];
|
|
1455
|
+
summary: {
|
|
1456
|
+
total: number;
|
|
1457
|
+
ok: number;
|
|
1458
|
+
failed: number;
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
/** Elemento del timeline: comentario o evento de historial. */
|
|
1462
|
+
type BudgetTimelineItem = {
|
|
1463
|
+
kind: 'COMMENT';
|
|
1464
|
+
at: string;
|
|
1465
|
+
comment: BudgetComment;
|
|
1466
|
+
} | {
|
|
1467
|
+
kind: 'EVENT';
|
|
1468
|
+
at: string;
|
|
1469
|
+
event: Record<string, unknown>;
|
|
1470
|
+
};
|
|
1471
|
+
/** Filtros para `getTimeline`. */
|
|
1472
|
+
interface BudgetTimelineFilter {
|
|
1473
|
+
cursor?: string;
|
|
1474
|
+
limit?: number;
|
|
1475
|
+
since?: string;
|
|
1476
|
+
until?: string;
|
|
1477
|
+
}
|
|
1478
|
+
/** Respuesta del timeline unificado. */
|
|
1479
|
+
interface BudgetTimelineResponse {
|
|
1480
|
+
items: BudgetTimelineItem[];
|
|
1481
|
+
pageInfo: {
|
|
1482
|
+
nextCursor?: string | null;
|
|
1483
|
+
hasMore: boolean;
|
|
1484
|
+
pageSize?: number;
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/**
|
|
1489
|
+
* Tipos del servicio de firmas electrónicas de presupuesto.
|
|
1490
|
+
*
|
|
1491
|
+
* El flujo de firma usa magic links (tokens de un solo uso, SHA-256 en BD,
|
|
1492
|
+
* snapshot del hash del documento al emitir). Un token vivo evoluciona por los
|
|
1493
|
+
* estados ACTIVE → CONSUMED | REVOKED | EXPIRED.
|
|
1494
|
+
*/
|
|
1495
|
+
/**
|
|
1496
|
+
* Estado agregado del proceso de firma para un presupuesto.
|
|
1497
|
+
* Pensado para representar el estado en la UI, no un enum de la BD.
|
|
1498
|
+
*/
|
|
1499
|
+
type SignatureStatus = 'NOT_SENT' | 'PENDING_SIGNATURE' | 'SIGNED' | 'REJECTED' | 'EXPIRED';
|
|
1500
|
+
/** Estado de un magic link concreto. */
|
|
1501
|
+
type SigningLinkStatus = 'ACTIVE' | 'CONSUMED' | 'REVOKED' | 'EXPIRED';
|
|
1502
|
+
/**
|
|
1503
|
+
* Firma electrónica registrada. `hashVersion` indica qué algoritmo de
|
|
1504
|
+
* serialización canónica se usó (1 = legado, 2 = extendido con descuentos,
|
|
1505
|
+
* impuestos, secciones, notas, términos).
|
|
1506
|
+
*/
|
|
1507
|
+
interface BudgetSignature {
|
|
1508
|
+
id: string;
|
|
1509
|
+
budgetId: string;
|
|
1510
|
+
budgetApprovalId?: string;
|
|
1511
|
+
signerName: string;
|
|
1512
|
+
signerEmail: string;
|
|
1513
|
+
signedAt: string;
|
|
1514
|
+
documentHash: string;
|
|
1515
|
+
hashVersion: number;
|
|
1516
|
+
/**
|
|
1517
|
+
* IP del firmante enmascarada (por ejemplo `***.***.x.xx`). Nunca se
|
|
1518
|
+
* devuelve la IP en claro por el endpoint público.
|
|
1519
|
+
*/
|
|
1520
|
+
ipAddressMasked?: string | null;
|
|
1521
|
+
userAgent?: string | null;
|
|
1522
|
+
signatureFileId?: string;
|
|
1523
|
+
signingTokenId?: string | null;
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Resultado de verificar la integridad de una firma. Si `valid === false`,
|
|
1527
|
+
* el documento ha cambiado después de la firma y la UI debe avisar al usuario.
|
|
1528
|
+
*/
|
|
1529
|
+
interface BudgetSignatureVerification {
|
|
1530
|
+
valid: boolean;
|
|
1531
|
+
expectedHash: string;
|
|
1532
|
+
actualHash: string;
|
|
1533
|
+
hashVersion: number;
|
|
1534
|
+
signedAt: string;
|
|
1535
|
+
signerName: string;
|
|
1536
|
+
signerEmail: string;
|
|
1537
|
+
ipAddressMasked?: string | null;
|
|
1538
|
+
userAgent?: string | null;
|
|
1539
|
+
signingTokenId?: string | null;
|
|
1540
|
+
}
|
|
1541
|
+
/** Entrada para generar un magic link de firma. */
|
|
1542
|
+
interface SigningLinkRequest {
|
|
1543
|
+
signerEmail: string;
|
|
1544
|
+
signerName?: string;
|
|
1545
|
+
/** Rango admitido: 1 a 168 horas (7 días). Por defecto 72 h. */
|
|
1546
|
+
expiresInHours?: number;
|
|
1547
|
+
/** Si es `true`, el backend envía el correo con el enlace al firmante. */
|
|
1548
|
+
sendEmail?: boolean;
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Respuesta de `generateSigningLink`. `signingUrl` puede ser `null` cuando se
|
|
1552
|
+
* reutiliza un token vivo existente (idempotencia por email) ya que el raw
|
|
1553
|
+
* token original no es recuperable.
|
|
1554
|
+
*/
|
|
1555
|
+
interface SigningLinkResponse {
|
|
1556
|
+
tokenId: string;
|
|
1557
|
+
signingUrl: string | null;
|
|
1558
|
+
expiresAt: string;
|
|
1559
|
+
/** `true` si el backend devolvió un token preexistente sin crear uno nuevo. */
|
|
1560
|
+
reused?: boolean;
|
|
1561
|
+
}
|
|
1562
|
+
/** Proyección segura de un token activo devuelta al listar. */
|
|
1563
|
+
interface SigningLinkSummary {
|
|
1564
|
+
tokenId: string;
|
|
1565
|
+
status?: SigningLinkStatus;
|
|
1566
|
+
signerEmail: string;
|
|
1567
|
+
signerName?: string | null;
|
|
1568
|
+
createdAt: string;
|
|
1569
|
+
expiresAt: string;
|
|
1570
|
+
consumedAt?: string | null;
|
|
1571
|
+
revokedAt?: string | null;
|
|
1572
|
+
sentTo?: string | null;
|
|
1573
|
+
createdBy?: {
|
|
1574
|
+
id: string;
|
|
1575
|
+
firstName?: string | null;
|
|
1576
|
+
lastName?: string | null;
|
|
1577
|
+
} | null;
|
|
1578
|
+
}
|
|
1579
|
+
/** Filtros para `listSigningLinks`. */
|
|
1580
|
+
interface ListSigningLinksFilter {
|
|
1581
|
+
includeRevoked?: boolean;
|
|
1582
|
+
includeExpired?: boolean;
|
|
1583
|
+
cursor?: string;
|
|
1584
|
+
limit?: number;
|
|
1585
|
+
}
|
|
1586
|
+
/** Respuesta al revocar un magic link. */
|
|
1587
|
+
interface RevokeSigningLinkResponse {
|
|
1588
|
+
tokenId: string;
|
|
1589
|
+
revokedAt: string;
|
|
1590
|
+
/** `true` si el token ya había sido revocado previamente. */
|
|
1591
|
+
alreadyRevoked?: boolean;
|
|
1592
|
+
}
|
|
1593
|
+
/** Tipos de eventos registrados en el audit trail legal. */
|
|
1594
|
+
type SignerAuditEventKind = 'ISSUED' | 'VIEWED' | 'PDF_DOWNLOADED' | 'APPROVED' | 'REJECTED' | 'EXPIRED' | 'REVOKED' | 'FAILED';
|
|
1595
|
+
/** Evento individual del audit trail. */
|
|
1596
|
+
interface SignerAuditEvent {
|
|
1597
|
+
id: string;
|
|
1598
|
+
event: SignerAuditEventKind;
|
|
1599
|
+
at: string;
|
|
1600
|
+
tokenId?: string | null;
|
|
1601
|
+
actorUserId?: string | null;
|
|
1602
|
+
ipAddress?: string | null;
|
|
1603
|
+
userAgent?: string | null;
|
|
1604
|
+
meta?: Record<string, unknown> | null;
|
|
1605
|
+
}
|
|
1606
|
+
/** Filtros para `getAuditTrail`. */
|
|
1607
|
+
interface AuditTrailFilter {
|
|
1608
|
+
tokenId?: string;
|
|
1609
|
+
cursor?: string;
|
|
1610
|
+
limit?: number;
|
|
1611
|
+
}
|
|
1612
|
+
/** Respuesta paginada del audit trail. */
|
|
1613
|
+
interface AuditTrailResponse {
|
|
1614
|
+
items: SignerAuditEvent[];
|
|
1615
|
+
nextCursor?: string | null;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Tipos relacionados con la configuración de la organización.
|
|
1620
|
+
*
|
|
1621
|
+
* Reflejan el DTO `OrganizationPublicSettingsResponseDto` del backend
|
|
1622
|
+
* (`apps/backend/src/modules/organization-settings/dto/organization-public-settings-response.dto.ts`).
|
|
1623
|
+
*/
|
|
1624
|
+
/**
|
|
1625
|
+
* Canal de contacto dinámico (email, teléfono, URL, etc.) configurado por la
|
|
1626
|
+
* organización.
|
|
1627
|
+
*/
|
|
1628
|
+
interface OrganizationContactChannel {
|
|
1629
|
+
/** Etiqueta legible (ej: "Soporte", "RRHH", "Comercial"). */
|
|
1630
|
+
label: string;
|
|
1631
|
+
/** Valor del canal (email, teléfono, URL). */
|
|
1632
|
+
value: string;
|
|
1633
|
+
/** Tipo de canal. Valores habituales: "email", "phone", "url". */
|
|
1634
|
+
type: string;
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Datos públicos de la organización devueltos por
|
|
1638
|
+
* `GET /organization-settings/public`.
|
|
1639
|
+
*
|
|
1640
|
+
* Son los campos que cualquier usuario autenticado puede leer para renderizar
|
|
1641
|
+
* branding, contacto y valores por defecto de facturación. No incluye
|
|
1642
|
+
* metadatos internos (id, createdAt, updatedAt, updatedById) ni los emails
|
|
1643
|
+
* legacy (ya transformados a `contactChannels`).
|
|
1644
|
+
*/
|
|
1645
|
+
interface OrganizationPublicSettings {
|
|
1646
|
+
companyName: string | null;
|
|
1647
|
+
companyLegalName: string | null;
|
|
1648
|
+
companyType: string | null;
|
|
1649
|
+
taxId: string | null;
|
|
1650
|
+
taxRegime: string | null;
|
|
1651
|
+
companyRegistryNumber: string | null;
|
|
1652
|
+
legalRepresentative: string | null;
|
|
1653
|
+
legalAddressStreet: string | null;
|
|
1654
|
+
legalAddressCity: string | null;
|
|
1655
|
+
legalAddressPostalCode: string | null;
|
|
1656
|
+
legalAddressCountry: string | null;
|
|
1657
|
+
operationalAddressName: string | null;
|
|
1658
|
+
operationalAddressStreet: string | null;
|
|
1659
|
+
operationalAddressCity: string | null;
|
|
1660
|
+
operationalAddressPostalCode: string | null;
|
|
1661
|
+
operationalAddressCountry: string | null;
|
|
1662
|
+
emailGeneral: string | null;
|
|
1663
|
+
phone: string | null;
|
|
1664
|
+
website: string | null;
|
|
1665
|
+
contactChannels: OrganizationContactChannel[] | null;
|
|
1666
|
+
bankName: string | null;
|
|
1667
|
+
bankIban: string | null;
|
|
1668
|
+
bankSwift: string | null;
|
|
1669
|
+
bankPaymentMethod: string | null;
|
|
1670
|
+
bankAccountHolder: string | null;
|
|
1671
|
+
defaultCurrency: string | null;
|
|
1672
|
+
defaultPaymentTermsDays: number | null;
|
|
1673
|
+
/** Nombre del impuesto por defecto (IVA, IGIC, VAT, TVA, MwSt, etc.). */
|
|
1674
|
+
defaultTaxName: string | null;
|
|
1675
|
+
/** Tasa por defecto en porcentaje (21 = 21 %). */
|
|
1676
|
+
defaultTaxRate: number | null;
|
|
1677
|
+
/** Código ISO 3166-1 alfa-2 del país principal (ES, FR, US, etc.). */
|
|
1678
|
+
country: string | null;
|
|
1679
|
+
invoicePrefix: string | null;
|
|
1680
|
+
invoiceLegalFooter: string | null;
|
|
1681
|
+
timezone: string | null;
|
|
1682
|
+
brandPrimaryColor: string | null;
|
|
1683
|
+
brandSecondaryColor: string | null;
|
|
1684
|
+
signatureImageUrl: string | null;
|
|
1685
|
+
documentSignerRole: string | null;
|
|
1686
|
+
logoUrl: string | null;
|
|
1687
|
+
logoDarkBgUrl: string | null;
|
|
1688
|
+
logoWidth: number | null;
|
|
1689
|
+
budgetBrandConfig: Record<string, unknown> | null;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
734
1692
|
/**
|
|
735
1693
|
* Servicio de errores del sistema
|
|
736
1694
|
* Maneja todas las operaciones relacionadas con el reporte y consulta de errores
|
|
@@ -1451,6 +2409,429 @@ declare class AiService {
|
|
|
1451
2409
|
private sleep;
|
|
1452
2410
|
}
|
|
1453
2411
|
|
|
2412
|
+
/**
|
|
2413
|
+
* Servicio de presupuestos (CRM Budgets).
|
|
2414
|
+
*
|
|
2415
|
+
* Cubre el CRUD completo, items, secciones, acciones (send/approve/reject/
|
|
2416
|
+
* cancel/duplicate/convert), adjuntos, historial, exportacion, operaciones
|
|
2417
|
+
* masivas y generacion asistida por IA.
|
|
2418
|
+
*/
|
|
2419
|
+
|
|
2420
|
+
/**
|
|
2421
|
+
* Opciones para la suscripcion SSE al job de generacion de items con IA.
|
|
2422
|
+
*/
|
|
2423
|
+
interface StreamAiJobOptions {
|
|
2424
|
+
/** Callback para cada evento de progreso. */
|
|
2425
|
+
onProgress?: (data: {
|
|
2426
|
+
status: string;
|
|
2427
|
+
progress: number;
|
|
2428
|
+
}) => void;
|
|
2429
|
+
/** Callback cuando el job se completa con exito. */
|
|
2430
|
+
onComplete?: (data: {
|
|
2431
|
+
items: AiGeneratedItem[];
|
|
2432
|
+
}) => void;
|
|
2433
|
+
/** Callback en caso de error. */
|
|
2434
|
+
onError?: (error: Error) => void;
|
|
2435
|
+
}
|
|
2436
|
+
/** Handle devuelto por streamGenerateItemsStatus para cerrar la conexion. */
|
|
2437
|
+
interface StreamAiJobHandle {
|
|
2438
|
+
close: () => void;
|
|
2439
|
+
}
|
|
2440
|
+
declare class BudgetsService {
|
|
2441
|
+
private readonly client;
|
|
2442
|
+
private readonly basePath;
|
|
2443
|
+
constructor(client: UtiliaClient);
|
|
2444
|
+
/**
|
|
2445
|
+
* Listar presupuestos aplicando filtros.
|
|
2446
|
+
*
|
|
2447
|
+
* @example
|
|
2448
|
+
* ```typescript
|
|
2449
|
+
* const page = await sdk.budgets.list({ status: 'SENT', page: 1, limit: 20 });
|
|
2450
|
+
* console.log(page.data, page.pagination.total);
|
|
2451
|
+
* ```
|
|
2452
|
+
*/
|
|
2453
|
+
list(filters?: BudgetFilters): Promise<BudgetListResponse>;
|
|
2454
|
+
/** Obtener el detalle completo de un presupuesto por UUID. */
|
|
2455
|
+
get(id: string): Promise<Budget>;
|
|
2456
|
+
/**
|
|
2457
|
+
* Crear un nuevo presupuesto.
|
|
2458
|
+
* Puede incluir items y secciones en la misma peticion.
|
|
2459
|
+
*/
|
|
2460
|
+
create(data: CreateBudgetInput): Promise<Budget>;
|
|
2461
|
+
/** Actualizar un presupuesto (solo en estado DRAFT salvo excepciones). */
|
|
2462
|
+
update(id: string, data: UpdateBudgetInput): Promise<Budget>;
|
|
2463
|
+
/** Soft delete (puede recuperarse). */
|
|
2464
|
+
delete(id: string): Promise<{
|
|
2465
|
+
message: string;
|
|
2466
|
+
}>;
|
|
2467
|
+
/**
|
|
2468
|
+
* Eliminar de forma permanente.
|
|
2469
|
+
* Solo disponible para SUPER_ADMIN en la organizacion origen.
|
|
2470
|
+
*/
|
|
2471
|
+
deletePermanent(id: string): Promise<{
|
|
2472
|
+
message: string;
|
|
2473
|
+
}>;
|
|
2474
|
+
/** Duplicar un presupuesto sin encadenarlo como nueva version. */
|
|
2475
|
+
duplicate(id: string, options?: DuplicateBudgetInput): Promise<Budget>;
|
|
2476
|
+
/** Crear una nueva version DRAFT del presupuesto, incrementando el contador. */
|
|
2477
|
+
createVersion(id: string): Promise<Budget>;
|
|
2478
|
+
/** Historial de versiones y cambios. */
|
|
2479
|
+
getHistory(id: string): Promise<BudgetHistoryEntry[]>;
|
|
2480
|
+
/** Presupuestos de un cliente. */
|
|
2481
|
+
listByClient(clientId: string): Promise<BudgetListItem[]>;
|
|
2482
|
+
/** Presupuestos de un proyecto. */
|
|
2483
|
+
listByProject(projectId: string): Promise<BudgetListItem[]>;
|
|
2484
|
+
/** Presupuestos de una oportunidad. */
|
|
2485
|
+
listByOpportunity(opportunityId: string): Promise<BudgetListItem[]>;
|
|
2486
|
+
/** Anyadir un item al presupuesto. */
|
|
2487
|
+
addItem(budgetId: string, data: CreateBudgetItemInput): Promise<BudgetItem>;
|
|
2488
|
+
/** Actualizar un item. */
|
|
2489
|
+
updateItem(budgetId: string, itemId: string, data: UpdateBudgetItemInput): Promise<BudgetItem>;
|
|
2490
|
+
/** Eliminar un item. */
|
|
2491
|
+
removeItem(budgetId: string, itemId: string): Promise<{
|
|
2492
|
+
message: string;
|
|
2493
|
+
}>;
|
|
2494
|
+
/** Aplicar un nuevo orden a los items del presupuesto. */
|
|
2495
|
+
reorderItems(budgetId: string, data: ReorderItemsInput): Promise<{
|
|
2496
|
+
message: string;
|
|
2497
|
+
}>;
|
|
2498
|
+
/** Listar secciones del presupuesto ordenadas por posicion y orden. */
|
|
2499
|
+
listSections(budgetId: string): Promise<BudgetSection[]>;
|
|
2500
|
+
/** Anyadir una seccion al presupuesto. */
|
|
2501
|
+
addSection(budgetId: string, data: CreateBudgetSectionInput): Promise<BudgetSection>;
|
|
2502
|
+
/** Actualizar una seccion existente. */
|
|
2503
|
+
updateSection(budgetId: string, sectionId: string, data: UpdateBudgetSectionInput): Promise<BudgetSection>;
|
|
2504
|
+
/** Eliminar una seccion. */
|
|
2505
|
+
removeSection(budgetId: string, sectionId: string): Promise<{
|
|
2506
|
+
message: string;
|
|
2507
|
+
}>;
|
|
2508
|
+
/** Reordenar secciones. */
|
|
2509
|
+
reorderSections(budgetId: string, data: ReorderSectionsInput): Promise<{
|
|
2510
|
+
message: string;
|
|
2511
|
+
}>;
|
|
2512
|
+
/** Enviar el presupuesto por correo al cliente. */
|
|
2513
|
+
send(id: string, data: SendBudgetInput): Promise<Budget>;
|
|
2514
|
+
/** Aprobar el presupuesto. */
|
|
2515
|
+
approve(id: string, data?: ApproveBudgetInput): Promise<Budget>;
|
|
2516
|
+
/** Rechazar el presupuesto. El motivo (reason) es obligatorio. */
|
|
2517
|
+
reject(id: string, data: RejectBudgetInput): Promise<Budget>;
|
|
2518
|
+
/** Cancelar el presupuesto. */
|
|
2519
|
+
cancel(id: string): Promise<Budget>;
|
|
2520
|
+
/**
|
|
2521
|
+
* Cambiar el estado del presupuesto directamente (uso administrativo).
|
|
2522
|
+
* Restringido a SUPER_ADMIN en el backend.
|
|
2523
|
+
*/
|
|
2524
|
+
changeStatus(id: string, status: BudgetStatus, reason?: string): Promise<Budget>;
|
|
2525
|
+
/** Convertir un presupuesto aprobado en un proyecto CRM. */
|
|
2526
|
+
convertToProject(id: string, options: ConvertToProjectInput): Promise<{
|
|
2527
|
+
projectId: string;
|
|
2528
|
+
}>;
|
|
2529
|
+
/** Convertir un presupuesto aprobado en factura. */
|
|
2530
|
+
convertToInvoice(id: string, options?: ConvertToInvoiceInput): Promise<{
|
|
2531
|
+
invoiceId: string;
|
|
2532
|
+
}>;
|
|
2533
|
+
/**
|
|
2534
|
+
* Generar el PDF del presupuesto para descarga.
|
|
2535
|
+
* Devuelve un Blob. Si el consumidor necesita una URL, usa `URL.createObjectURL`.
|
|
2536
|
+
*/
|
|
2537
|
+
generatePdf(id: string): Promise<Blob>;
|
|
2538
|
+
/**
|
|
2539
|
+
* Visualizar el PDF del presupuesto (Content-Disposition inline).
|
|
2540
|
+
* Devuelve un Blob.
|
|
2541
|
+
*/
|
|
2542
|
+
viewPdf(id: string): Promise<Blob>;
|
|
2543
|
+
/**
|
|
2544
|
+
* Construir la URL del PDF del presupuesto (util para <iframe>, <embed>, etc.).
|
|
2545
|
+
* Incluye las credenciales en query string para funcionar en etiquetas HTML
|
|
2546
|
+
* que no pueden anyadir headers personalizados.
|
|
2547
|
+
*/
|
|
2548
|
+
getPdfUrl(id: string): string;
|
|
2549
|
+
/** Listar adjuntos del presupuesto. */
|
|
2550
|
+
getAttachments(budgetId: string): Promise<BudgetAttachment[]>;
|
|
2551
|
+
/**
|
|
2552
|
+
* Subir un adjunto al presupuesto.
|
|
2553
|
+
*
|
|
2554
|
+
* @param budgetId - UUID del presupuesto
|
|
2555
|
+
* @param file - Archivo a subir (File o Blob)
|
|
2556
|
+
* @param meta - Nombre visible y descripcion opcionales
|
|
2557
|
+
*/
|
|
2558
|
+
uploadAttachment(budgetId: string, file: File | Blob, meta?: {
|
|
2559
|
+
name?: string;
|
|
2560
|
+
description?: string;
|
|
2561
|
+
}): Promise<BudgetAttachment>;
|
|
2562
|
+
/** Eliminar un adjunto del presupuesto. */
|
|
2563
|
+
deleteAttachment(budgetId: string, attachmentId: string): Promise<{
|
|
2564
|
+
message: string;
|
|
2565
|
+
}>;
|
|
2566
|
+
/**
|
|
2567
|
+
* Subir una imagen para el editor WYSIWYG.
|
|
2568
|
+
* La imagen no aparece como adjunto en el File Manager: solo devuelve la URL
|
|
2569
|
+
* para incrustarla en el contenido del presupuesto.
|
|
2570
|
+
*/
|
|
2571
|
+
uploadEditorImage(budgetId: string, file: File | Blob): Promise<UploadedBudgetImage>;
|
|
2572
|
+
/** Proximo codigo sugerido segun la configuracion de numeracion. */
|
|
2573
|
+
getNextCode(): Promise<NextCodeResponse>;
|
|
2574
|
+
/** Comprobar si un codigo ya esta en uso. */
|
|
2575
|
+
checkCode(code: string, excludeId?: string): Promise<CheckCodeResponse>;
|
|
2576
|
+
/** Estadisticas agregadas (totales, tasa aprobacion, etc.). */
|
|
2577
|
+
getStats(filters?: BudgetFilters): Promise<Record<string, unknown>>;
|
|
2578
|
+
/** Ejecutar una operacion masiva (delete / cancel / change-status). */
|
|
2579
|
+
bulk(operation: BulkBudgetOperation, ids: string[], options?: BulkBudgetOptions): Promise<BulkBudgetResult>;
|
|
2580
|
+
/**
|
|
2581
|
+
* Exportar el listado filtrado en el formato indicado.
|
|
2582
|
+
* De momento solo se soporta `csv`. Devuelve un Blob.
|
|
2583
|
+
*/
|
|
2584
|
+
export(filters?: BudgetFilters, format?: BudgetExportFormat): Promise<Blob>;
|
|
2585
|
+
/**
|
|
2586
|
+
* Encolar un job asincrono para generar items del presupuesto a partir
|
|
2587
|
+
* de un texto en lenguaje natural. Devuelve el `jobId` para seguir el
|
|
2588
|
+
* progreso vía `streamGenerateItemsStatus`.
|
|
2589
|
+
*/
|
|
2590
|
+
generateItemsWithAi(data: GenerateItemsAiInput): Promise<GenerateItemsAiJob>;
|
|
2591
|
+
/**
|
|
2592
|
+
* Suscribirse al progreso (SSE) del job de generacion de items con IA.
|
|
2593
|
+
* Requiere EventSource en el entorno.
|
|
2594
|
+
*/
|
|
2595
|
+
streamGenerateItemsStatus(jobId: string, options?: StreamAiJobOptions): StreamAiJobHandle;
|
|
2596
|
+
/**
|
|
2597
|
+
* Generar un presupuesto completo (secciones + items) a partir de un texto.
|
|
2598
|
+
* Devuelve la estructura sugerida sin crear el presupuesto.
|
|
2599
|
+
*/
|
|
2600
|
+
generateCompleteWithAi(data: GenerateItemsAiInput): Promise<GenerateCompleteAiResult>;
|
|
2601
|
+
/** Generar unicamente secciones sugeridas para un presupuesto existente. */
|
|
2602
|
+
generateSectionsWithAi(data: GenerateItemsAiInput): Promise<GenerateSectionsAiResult>;
|
|
2603
|
+
/**
|
|
2604
|
+
* Convierte los filtros a un objeto plano apto para query string.
|
|
2605
|
+
* Aplana arrays en formato coma-separado (patron del backend).
|
|
2606
|
+
*/
|
|
2607
|
+
private serializeFilters;
|
|
2608
|
+
/**
|
|
2609
|
+
* Descargar una respuesta binaria (PDF, CSV) respetando el auth del cliente.
|
|
2610
|
+
* Usa `buildSseUrl` para añadir las credenciales en la URL cuando la ruta
|
|
2611
|
+
* no pueda llevarlas en headers (p. ej. etiquetas `<a href>`).
|
|
2612
|
+
*/
|
|
2613
|
+
private fetchBinary;
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
/**
|
|
2617
|
+
* Servicio de plantillas de presupuesto (CRM Budget Templates).
|
|
2618
|
+
*
|
|
2619
|
+
* Las plantillas aceleran la creacion de presupuestos reutilizando
|
|
2620
|
+
* secciones e items predefinidos. Se distinguen:
|
|
2621
|
+
* - Plantillas del sistema (`isSystemDefault: true`), inmutables.
|
|
2622
|
+
* - Plantillas personalizadas del usuario.
|
|
2623
|
+
*/
|
|
2624
|
+
|
|
2625
|
+
declare class BudgetTemplatesService {
|
|
2626
|
+
private readonly client;
|
|
2627
|
+
private readonly basePath;
|
|
2628
|
+
private readonly budgetsPath;
|
|
2629
|
+
constructor(client: UtiliaClient);
|
|
2630
|
+
/**
|
|
2631
|
+
* Listar plantillas activas.
|
|
2632
|
+
* Las plantillas del sistema aparecen primero, seguidas de las
|
|
2633
|
+
* personalizadas ordenadas por fecha de creacion descendente.
|
|
2634
|
+
*/
|
|
2635
|
+
list(): Promise<BudgetTemplate[]>;
|
|
2636
|
+
/** Obtener el detalle de una plantilla por UUID. */
|
|
2637
|
+
get(id: string): Promise<BudgetTemplate>;
|
|
2638
|
+
/** Crear una plantilla personalizada. */
|
|
2639
|
+
create(data: CreateBudgetTemplateInput): Promise<BudgetTemplate>;
|
|
2640
|
+
/** Actualizar una plantilla personalizada (las del sistema son inmutables). */
|
|
2641
|
+
update(id: string, data: UpdateBudgetTemplateInput): Promise<BudgetTemplate>;
|
|
2642
|
+
/** Archivar (soft delete) una plantilla personalizada. */
|
|
2643
|
+
delete(id: string): Promise<{
|
|
2644
|
+
message: string;
|
|
2645
|
+
}>;
|
|
2646
|
+
/**
|
|
2647
|
+
* Crear una plantilla personalizada copiando items y secciones de un
|
|
2648
|
+
* presupuesto existente.
|
|
2649
|
+
*/
|
|
2650
|
+
createFromBudget(budgetId: string, data: CreateTemplateFromBudgetInput): Promise<BudgetTemplate>;
|
|
2651
|
+
/**
|
|
2652
|
+
* Crear un presupuesto DRAFT aplicando una plantilla.
|
|
2653
|
+
* Copia los items/secciones de la plantilla y asigna cliente/oportunidad.
|
|
2654
|
+
*/
|
|
2655
|
+
applyTemplate(templateId: string, data: ApplyTemplateInput): Promise<Budget>;
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2658
|
+
/**
|
|
2659
|
+
* Servicio de comentarios de presupuesto.
|
|
2660
|
+
*
|
|
2661
|
+
* Cubre el CRUD completo, la creación masiva tolerante a fallos y el timeline
|
|
2662
|
+
* unificado (comentarios + eventos del historial). La capa de permisos es
|
|
2663
|
+
* responsabilidad del backend: el SDK se limita a enviar la petición con la
|
|
2664
|
+
* visibilidad solicitada.
|
|
2665
|
+
*/
|
|
2666
|
+
|
|
2667
|
+
declare class BudgetCommentsService {
|
|
2668
|
+
private readonly client;
|
|
2669
|
+
private readonly basePath;
|
|
2670
|
+
constructor(client: UtiliaClient);
|
|
2671
|
+
/**
|
|
2672
|
+
* Listar comentarios del presupuesto.
|
|
2673
|
+
*
|
|
2674
|
+
* @param budgetId - UUID del presupuesto.
|
|
2675
|
+
* @param filter - Filtros de visibilidad, paginación y rango de fechas.
|
|
2676
|
+
*
|
|
2677
|
+
* @example
|
|
2678
|
+
* ```typescript
|
|
2679
|
+
* const page = await sdk.budgetComments.list(budgetId, { visibility: 'CLIENT', page: 1, limit: 20 });
|
|
2680
|
+
* page.data.forEach(c => console.log(c.body));
|
|
2681
|
+
* ```
|
|
2682
|
+
*/
|
|
2683
|
+
list(budgetId: string, filter?: ListBudgetCommentsFilter): Promise<BudgetCommentListResponse>;
|
|
2684
|
+
/**
|
|
2685
|
+
* Obtener un comentario por su ID.
|
|
2686
|
+
*
|
|
2687
|
+
* Nota: el backend actual no expone `GET /comments/:commentId` a nivel de
|
|
2688
|
+
* REST. El SDK lo emula filtrando localmente el resultado del listado. Si
|
|
2689
|
+
* en el futuro se añade un endpoint dedicado, este método se puede migrar
|
|
2690
|
+
* sin romper la firma.
|
|
2691
|
+
*/
|
|
2692
|
+
get(budgetId: string, commentId: string): Promise<BudgetComment>;
|
|
2693
|
+
/**
|
|
2694
|
+
* Crear un comentario en el presupuesto.
|
|
2695
|
+
*
|
|
2696
|
+
* La visibilidad (INTERNAL / CLIENT) debe ser compatible con los permisos
|
|
2697
|
+
* del usuario autenticado. Las menciones solo tienen efecto en comentarios
|
|
2698
|
+
* internos.
|
|
2699
|
+
*/
|
|
2700
|
+
create(budgetId: string, input: CreateBudgetCommentInput): Promise<BudgetComment>;
|
|
2701
|
+
/** Actualizar el cuerpo de un comentario. Solo autor o SUPER_ADMIN. */
|
|
2702
|
+
update(budgetId: string, commentId: string, input: UpdateBudgetCommentInput): Promise<BudgetComment>;
|
|
2703
|
+
/** Eliminar un comentario. Solo autor o SUPER_ADMIN. */
|
|
2704
|
+
remove(budgetId: string, commentId: string): Promise<{
|
|
2705
|
+
message: string;
|
|
2706
|
+
}>;
|
|
2707
|
+
/**
|
|
2708
|
+
* Creación masiva tolerante a fallos (saga).
|
|
2709
|
+
*
|
|
2710
|
+
* Nota: a día de hoy, el backend expone el bulk únicamente a través de la
|
|
2711
|
+
* herramienta MCP `crm_budget_comments.bulk_create`. Para consumirlo desde
|
|
2712
|
+
* REST, el SDK llama secuencialmente a `create` y agrega el resultado,
|
|
2713
|
+
* respetando el contrato del método. Sustituir cuando exista un endpoint
|
|
2714
|
+
* REST dedicado.
|
|
2715
|
+
*/
|
|
2716
|
+
bulkCreate(budgetId: string, items: CreateBudgetCommentInput[], options?: {
|
|
2717
|
+
idempotencyKey?: string;
|
|
2718
|
+
}): Promise<BudgetCommentBulkResult>;
|
|
2719
|
+
/**
|
|
2720
|
+
* Devuelve el timeline unificado: comentarios + eventos de historial del
|
|
2721
|
+
* presupuesto ordenados cronológicamente descendente.
|
|
2722
|
+
*
|
|
2723
|
+
* Nota: el backend expone esta vista agregada a través de la herramienta MCP
|
|
2724
|
+
* `crm_budget_comments.get_timeline`. Hasta que se habilite un endpoint REST
|
|
2725
|
+
* dedicado, el SDK devuelve los comentarios paginados y un `items` sólo con
|
|
2726
|
+
* kind `COMMENT`. Se marca como follow-up.
|
|
2727
|
+
*/
|
|
2728
|
+
getTimeline(budgetId: string, filter?: BudgetTimelineFilter): Promise<BudgetTimelineResponse>;
|
|
2729
|
+
private serializeListFilter;
|
|
2730
|
+
private serializeTimelineFilter;
|
|
2731
|
+
private normalizeBulkResult;
|
|
2732
|
+
private mapErrorCode;
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
/**
|
|
2736
|
+
* Servicio de firmas electrónicas de presupuesto.
|
|
2737
|
+
*
|
|
2738
|
+
* Gestiona:
|
|
2739
|
+
* - Magic links de firma (generar, listar, revocar).
|
|
2740
|
+
* - Consulta y verificación de firmas registradas.
|
|
2741
|
+
* - Descarga del certificado legal en PDF.
|
|
2742
|
+
* - Audit trail de eventos.
|
|
2743
|
+
*
|
|
2744
|
+
* El SDK no consume el flujo público del firmante (`/public/budgets/sign/:token`),
|
|
2745
|
+
* ya que ese flujo no usa autenticación y se accede desde el frontend público
|
|
2746
|
+
* `/sign/[token]`.
|
|
2747
|
+
*/
|
|
2748
|
+
|
|
2749
|
+
declare class BudgetSignaturesService {
|
|
2750
|
+
private readonly client;
|
|
2751
|
+
private readonly basePath;
|
|
2752
|
+
constructor(client: UtiliaClient);
|
|
2753
|
+
/** Listar todas las firmas asociadas al presupuesto. */
|
|
2754
|
+
list(budgetId: string): Promise<BudgetSignature[]>;
|
|
2755
|
+
/** Obtener el detalle de una firma concreta. */
|
|
2756
|
+
get(budgetId: string, signatureId: string): Promise<BudgetSignature>;
|
|
2757
|
+
/**
|
|
2758
|
+
* Verificar la integridad de una firma. Recalcula el hash del documento con
|
|
2759
|
+
* la versión (`hashVersion`) con la que se firmó originalmente y lo compara.
|
|
2760
|
+
*
|
|
2761
|
+
* Si `valid === false`, el documento ha sido modificado después de firmar.
|
|
2762
|
+
*/
|
|
2763
|
+
verify(budgetId: string, signatureId: string): Promise<BudgetSignatureVerification>;
|
|
2764
|
+
/**
|
|
2765
|
+
* Descargar el certificado legal de una firma como Blob.
|
|
2766
|
+
*
|
|
2767
|
+
* Ideal para consumidores que necesiten guardar el PDF localmente o abrirlo
|
|
2768
|
+
* con `URL.createObjectURL`.
|
|
2769
|
+
*/
|
|
2770
|
+
downloadCertificate(budgetId: string, signatureId: string): Promise<Blob>;
|
|
2771
|
+
/**
|
|
2772
|
+
* Construir la URL del certificado (útil para `<iframe>` o enlaces directos).
|
|
2773
|
+
* Incluye las credenciales en query string cuando el SDK usa API key.
|
|
2774
|
+
*/
|
|
2775
|
+
getCertificateUrl(budgetId: string, signatureId: string): string;
|
|
2776
|
+
/**
|
|
2777
|
+
* Generar un magic link de firma. El endpoint es idempotente para la tupla
|
|
2778
|
+
* (budgetId, signerEmail): si ya existe un token vivo se devuelve con
|
|
2779
|
+
* `reused: true` y `signingUrl: null` (el raw token original no se
|
|
2780
|
+
* recupera).
|
|
2781
|
+
*/
|
|
2782
|
+
generateSigningLink(budgetId: string, input: SigningLinkRequest): Promise<SigningLinkResponse>;
|
|
2783
|
+
/**
|
|
2784
|
+
* Listar los magic links vivos del presupuesto (no usados, no revocados y no
|
|
2785
|
+
* expirados). Los filtros `includeRevoked`/`includeExpired` se reservan para
|
|
2786
|
+
* cuando el backend exponga la vista extendida.
|
|
2787
|
+
*/
|
|
2788
|
+
listSigningLinks(budgetId: string, filter?: ListSigningLinksFilter): Promise<SigningLinkSummary[]>;
|
|
2789
|
+
/** Revocar un magic link. Idempotente: llamarla dos veces no falla. */
|
|
2790
|
+
revokeSigningLink(budgetId: string, tokenId: string): Promise<RevokeSigningLinkResponse>;
|
|
2791
|
+
/**
|
|
2792
|
+
* Audit trail paginado por cursor de los eventos de firma del presupuesto
|
|
2793
|
+
* (emisión, visualización, descarga de PDF, aprobación, rechazo,
|
|
2794
|
+
* expiración, revocación, fallos).
|
|
2795
|
+
*/
|
|
2796
|
+
getAuditTrail(budgetId: string, filter?: AuditTrailFilter): Promise<SignerAuditEvent[]>;
|
|
2797
|
+
private serializeSigningLinksFilter;
|
|
2798
|
+
private serializeAuditFilter;
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
/**
|
|
2802
|
+
* Servicio de configuración de organización.
|
|
2803
|
+
*
|
|
2804
|
+
* Expone los datos públicos de la organización a consumidores externos
|
|
2805
|
+
* (portal de cliente, integraciones, agentes IA) sin exponer metadatos
|
|
2806
|
+
* internos. Los datos devueltos incluyen branding, valores fiscales por
|
|
2807
|
+
* defecto y preferencias regionales que son útiles durante el onboarding
|
|
2808
|
+
* o para auto-rellenar formularios.
|
|
2809
|
+
*/
|
|
2810
|
+
|
|
2811
|
+
declare class OrganizationSettingsService {
|
|
2812
|
+
private readonly client;
|
|
2813
|
+
private readonly basePath;
|
|
2814
|
+
constructor(client: UtiliaClient);
|
|
2815
|
+
/**
|
|
2816
|
+
* Obtener los datos públicos de la organización.
|
|
2817
|
+
*
|
|
2818
|
+
* Incluye identidad corporativa, branding, configuración de facturación
|
|
2819
|
+
* (moneda, impuesto por defecto, país) y canales de contacto.
|
|
2820
|
+
*
|
|
2821
|
+
* @returns Configuración pública de la organización.
|
|
2822
|
+
*
|
|
2823
|
+
* @example
|
|
2824
|
+
* ```typescript
|
|
2825
|
+
* const settings = await sdk.organizationSettings.getPublicSettings();
|
|
2826
|
+
* console.log(settings.defaultCurrency); // "EUR"
|
|
2827
|
+
* console.log(settings.defaultTaxName); // "IVA"
|
|
2828
|
+
* console.log(settings.defaultTaxRate); // 21
|
|
2829
|
+
* console.log(settings.country); // "ES"
|
|
2830
|
+
* ```
|
|
2831
|
+
*/
|
|
2832
|
+
getPublicSettings(): Promise<OrganizationPublicSettings>;
|
|
2833
|
+
}
|
|
2834
|
+
|
|
1454
2835
|
/**
|
|
1455
2836
|
* Codigos de error del SDK
|
|
1456
2837
|
*/
|
|
@@ -1634,6 +3015,11 @@ declare const SDK_LIMITS: {
|
|
|
1634
3015
|
* - `tickets`: Operaciones con tickets de soporte
|
|
1635
3016
|
* - `users`: Operaciones con usuarios externos
|
|
1636
3017
|
* - `ai`: Funcionalidades de IA (transcripción, sugerencias)
|
|
3018
|
+
* - `budgets`: Presupuestos CRM (CRUD, items, secciones, flujo, IA, PDF)
|
|
3019
|
+
* - `budgetTemplates`: Plantillas de presupuesto reutilizables
|
|
3020
|
+
* - `budgetComments`: Comentarios internos y dirigidos al cliente de presupuestos
|
|
3021
|
+
* - `budgetSignatures`: Firma electrónica con magic link, verificación y certificado
|
|
3022
|
+
* - `organizationSettings`: Datos públicos de la organización (branding, fiscal, contacto)
|
|
1637
3023
|
*/
|
|
1638
3024
|
declare class UtiliaSDK {
|
|
1639
3025
|
private readonly _client;
|
|
@@ -1647,6 +3033,16 @@ declare class UtiliaSDK {
|
|
|
1647
3033
|
readonly users: UsersService;
|
|
1648
3034
|
/** Servicio de IA para transcripción y sugerencias */
|
|
1649
3035
|
readonly ai: AiService;
|
|
3036
|
+
/** Servicio de presupuestos CRM */
|
|
3037
|
+
readonly budgets: BudgetsService;
|
|
3038
|
+
/** Servicio de plantillas de presupuesto CRM */
|
|
3039
|
+
readonly budgetTemplates: BudgetTemplatesService;
|
|
3040
|
+
/** Servicio de comentarios de presupuesto (INTERNAL / CLIENT) */
|
|
3041
|
+
readonly budgetComments: BudgetCommentsService;
|
|
3042
|
+
/** Servicio de firmas electrónicas y magic links de presupuesto */
|
|
3043
|
+
readonly budgetSignatures: BudgetSignaturesService;
|
|
3044
|
+
/** Servicio de configuración pública de la organización */
|
|
3045
|
+
readonly organizationSettings: OrganizationSettingsService;
|
|
1650
3046
|
/**
|
|
1651
3047
|
* Crea una nueva instancia del SDK
|
|
1652
3048
|
*
|
|
@@ -1684,4 +3080,4 @@ declare class UtiliaSDK {
|
|
|
1684
3080
|
get oauth(): OAuthService;
|
|
1685
3081
|
}
|
|
1686
3082
|
|
|
1687
|
-
export { type AddMessageInput, type AiJobStatus, type AiSuggestInput, type AiSuggestions, type AiUserAction, type CreateTicketInput, type CreateTicketUser, type CreatedMessage, type CreatedTicket, ErrorCode, type ErrorFilters, type ErrorHttpMethod, type ErrorSeverity, type ErrorStats, type ExternalUser, type FileQuota, FileTokenStorage, type GetSuggestionsOptions, type IdentifyUserInput, type LoginUrlResult, MemoryTokenStorage, type MessageAuthor, type OAuthConfig, OAuthService, type OAuthTokens, type OAuthUserInfo, type PKCEChallenge, type PaginatedResponse, type PaginationMeta, type PendingOAuthState, type PopupLoginOptions, type ReportErrorInput, type ReportedError, type RequestConfig, SDK_LIMITS, type SseEvent, type StreamSuggestionsHandle, type StreamSuggestionsOptions, type StreamTranscriptionOptions, type SystemError, type TicketAttachment, type TicketCategory, type TicketContext, type TicketDetail, type TicketFilters, type TicketListItem, type TicketMessage, type TicketPriority, type TicketReporter, type TicketStatus, type TokenStorage, type TrackAiActionInput, type TranscriptionJobStatus, type UnreadCount, type UploadFileOptions, type UploadedFile, UtiliaSDK, type UtiliaSDKConfig, UtiliaSDKError, base64UrlEncode, generateCodeChallenge, generateCodeVerifier };
|
|
3083
|
+
export { type AddMessageInput, type AiGeneratedItem, type AiGeneratedSection, type AiJobStatus, type AiSuggestInput, type AiSuggestions, type AiUserAction, type ApplyTemplateInput, type ApproveBudgetInput, type ApproverType, type AuditTrailFilter, type AuditTrailResponse, type AuthorizedApp, BUDGET_WEBHOOK_EVENTS, type Budget, type BudgetApproval, type BudgetAttachment, type BudgetClientRef, type BudgetComment, type BudgetCommentAuthor, type BudgetCommentAuthorKind, type BudgetCommentBulkFailure, type BudgetCommentBulkResult, type BudgetCommentListResponse, type BudgetCommentPageInfo, type BudgetCommentPortalAuthor, type BudgetCommentVisibility, type BudgetExportFormat, type BudgetFilters, type BudgetHistoryEntry, type BudgetItem, type BudgetItemOrder, type BudgetItemType, type BudgetListItem, type BudgetListResponse, type BudgetOpportunityRef, type BudgetPdfUrlResponse, type BudgetProjectRef, type BudgetSection, type BudgetSectionPosition, type BudgetSectionType, type BudgetSignature, type BudgetSignatureVerification, type BudgetStatus, type BudgetTemplate, type BudgetTemplateItemJson, type BudgetTemplateSectionJson, type BudgetTimelineFilter, type BudgetTimelineItem, type BudgetTimelineResponse, type BudgetUserRef, type BudgetWebhookEvent, type BulkBudgetInput, type BulkBudgetOperation, type BulkBudgetOptions, type BulkBudgetResult, type BulkBudgetResultItem, type ChangeStatusInput, type CheckCodeResponse, type ConvertToInvoiceInput, type ConvertToProjectInput, type CreateBudgetCommentInput, type CreateBudgetInput, type CreateBudgetItemInput, type CreateBudgetSectionInput, type CreateBudgetTemplateInput, type CreateTemplateFromBudgetInput, type CreateTicketInput, type CreateTicketUser, type CreatedMessage, type CreatedTicket, type DuplicateBudgetInput, ErrorCode, type ErrorFilters, type ErrorHttpMethod, type ErrorSeverity, type ErrorStats, type ExternalUser, type FileQuota, FileTokenStorage, type GenerateCompleteAiResult, type GenerateItemsAiInput, type GenerateItemsAiJob, type GenerateSectionsAiResult, type GetSuggestionsOptions, type IdentifyUserInput, type IntrospectResponse, type ListBudgetCommentsFilter, type ListSigningLinksFilter, type LoginUrlResult, MemoryTokenStorage, type MessageAuthor, type NextCodeResponse, type OAuthConfig, OAuthService, type OAuthTokens, type OAuthUserInfo, type OidcAuthorizationOptions, type OrganizationContactChannel, type OrganizationPublicSettings, type PKCEChallenge, type PaginatedResponse, type PaginationMeta, type PaymentMethod, type PendingOAuthState, type PopupLoginOptions, type RejectBudgetInput, type ReorderItemsInput, type ReorderSectionsInput, type ReportErrorInput, type ReportedError, type RequestConfig, type RevokeSigningLinkResponse, SDK_LIMITS, type SendBudgetInput, type SignatureStatus, type SignerAuditEvent, type SignerAuditEventKind, type SigningLinkRequest, type SigningLinkResponse, type SigningLinkStatus, type SigningLinkSummary, type SortOrder, type SseEvent, type StreamSuggestionsHandle, type StreamSuggestionsOptions, type StreamTranscriptionOptions, type SystemError, type TicketAttachment, type TicketCategory, type TicketContext, type TicketDetail, type TicketFilters, type TicketListItem, type TicketMessage, type TicketPriority, type TicketReporter, type TicketStatus, type TokenStorage, type TrackAiActionInput, type TranscriptionJobStatus, type UnreadCount, type UpdateBudgetCommentInput, type UpdateBudgetInput, type UpdateBudgetItemInput, type UpdateBudgetSectionInput, type UpdateBudgetTemplateInput, type UploadFileOptions, type UploadedBudgetImage, type UploadedFile, UtiliaSDK, type UtiliaSDKConfig, UtiliaSDKError, base64UrlEncode, generateCodeChallenge, generateCodeVerifier };
|