@scell/sdk 1.2.0 → 1.4.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.
@@ -0,0 +1,429 @@
1
+ /**
2
+ * Tenant Incoming Invoices Resource
3
+ *
4
+ * Manage incoming invoices (purchase invoices) for sub-tenants.
5
+ * Incoming invoices are invoices received by a sub-tenant from external suppliers.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import type { HttpClient, RequestOptions } from '../client.js';
11
+ import type {
12
+ MessageResponse,
13
+ PaginatedResponse,
14
+ SingleResponse,
15
+ } from '../types/common.js';
16
+ import type {
17
+ CreateIncomingInvoiceParams,
18
+ TenantInvoice,
19
+ TenantInvoiceFilters,
20
+ } from '../types/tenant-invoices.js';
21
+ import type { RejectionCode } from '../types/invoices.js';
22
+
23
+ /**
24
+ * Input for accepting an incoming invoice
25
+ */
26
+ export interface AcceptIncomingInvoiceInput {
27
+ /** Expected payment date (YYYY-MM-DD) */
28
+ payment_date?: string | undefined;
29
+ /** Optional note about acceptance */
30
+ note?: string | undefined;
31
+ }
32
+
33
+ /**
34
+ * Input for rejecting an incoming invoice
35
+ */
36
+ export interface RejectIncomingInvoiceInput {
37
+ /** Reason for rejection */
38
+ reason: string;
39
+ /** Standardized rejection code */
40
+ reason_code?: RejectionCode | undefined;
41
+ }
42
+
43
+ /**
44
+ * Input for marking an invoice as paid
45
+ */
46
+ export interface MarkPaidIncomingInvoiceInput {
47
+ /** Payment reference (bank transfer ID, check number, etc.) */
48
+ payment_reference?: string | undefined;
49
+ /** Payment date (ISO 8601) - defaults to current date/time */
50
+ paid_at?: string | undefined;
51
+ /** Optional note about the payment */
52
+ note?: string | undefined;
53
+ }
54
+
55
+ /**
56
+ * Tenant Incoming Invoices API resource
57
+ *
58
+ * Provides operations for managing incoming invoices (purchase invoices)
59
+ * received by sub-tenants from external suppliers.
60
+ *
61
+ * In the French e-invoicing lifecycle, incoming invoices go through these states:
62
+ * - pending: Awaiting review
63
+ * - accepted: Approved for payment
64
+ * - rejected: Disputed/refused
65
+ * - paid: Payment completed
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * import { ScellTenantClient } from '@scell/sdk';
70
+ *
71
+ * const client = new ScellTenantClient('your-tenant-key');
72
+ *
73
+ * // Create an incoming invoice for a sub-tenant
74
+ * const { data: invoice } = await client.incomingInvoices.create(
75
+ * 'sub-tenant-uuid',
76
+ * {
77
+ * invoice_number: 'SUPP-2026-001',
78
+ * company_id: 'company-uuid',
79
+ * seller: {
80
+ * company_name: 'Supplier Corp',
81
+ * siren: '123456789',
82
+ * address: {
83
+ * line1: '789 Rue Fournisseur',
84
+ * postal_code: '33000',
85
+ * city: 'Bordeaux',
86
+ * country: 'FR'
87
+ * },
88
+ * email: 'invoices@supplier.com'
89
+ * },
90
+ * lines: [{
91
+ * description: 'Raw materials',
92
+ * quantity: 100,
93
+ * unit_price: 10,
94
+ * tax_rate: 20,
95
+ * total_ht: 1000,
96
+ * total_tax: 200,
97
+ * total_ttc: 1200
98
+ * }],
99
+ * issue_date: '2026-01-20',
100
+ * total_ht: 1000,
101
+ * total_ttc: 1200
102
+ * }
103
+ * );
104
+ *
105
+ * // Accept the invoice
106
+ * await client.incomingInvoices.accept(invoice.id, {
107
+ * payment_date: '2026-02-20',
108
+ * note: 'Approved by finance department'
109
+ * });
110
+ *
111
+ * // Later, mark as paid
112
+ * await client.incomingInvoices.markPaid(invoice.id, {
113
+ * payment_reference: 'VIR-2026-0150'
114
+ * });
115
+ * ```
116
+ */
117
+ export class TenantIncomingInvoicesResource {
118
+ constructor(private readonly http: HttpClient) {}
119
+
120
+ /**
121
+ * Create a new incoming invoice for a sub-tenant
122
+ *
123
+ * Creates a purchase invoice received by a sub-tenant from an external supplier.
124
+ * The seller's SIREN is validated using the Luhn algorithm.
125
+ *
126
+ * @param subTenantId - Sub-tenant UUID
127
+ * @param params - Invoice creation parameters
128
+ * @param requestOptions - Optional request configuration
129
+ * @returns Created invoice
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const { data: invoice } = await client.incomingInvoices.create(
134
+ * 'sub-tenant-uuid',
135
+ * {
136
+ * invoice_number: 'SUPP-2026-001',
137
+ * company_id: 'company-uuid',
138
+ * seller: {
139
+ * company_name: 'Acme Supplies',
140
+ * siren: '123456789',
141
+ * siret: '12345678901234',
142
+ * vat_number: 'FR12123456789',
143
+ * address: {
144
+ * line1: '123 Industrial Park',
145
+ * postal_code: '31000',
146
+ * city: 'Toulouse',
147
+ * country: 'FR'
148
+ * },
149
+ * email: 'billing@acme-supplies.com'
150
+ * },
151
+ * lines: [
152
+ * {
153
+ * description: 'Widget A - Bulk order',
154
+ * quantity: 500,
155
+ * unit_price: 2.50,
156
+ * tax_rate: 20,
157
+ * total_ht: 1250,
158
+ * total_tax: 250,
159
+ * total_ttc: 1500
160
+ * }
161
+ * ],
162
+ * issue_date: '2026-01-15',
163
+ * due_date: '2026-02-15',
164
+ * total_ht: 1250,
165
+ * total_ttc: 1500
166
+ * }
167
+ * );
168
+ *
169
+ * console.log('Incoming invoice created:', invoice.invoice_number);
170
+ * ```
171
+ */
172
+ async create(
173
+ subTenantId: string,
174
+ params: CreateIncomingInvoiceParams,
175
+ requestOptions?: RequestOptions
176
+ ): Promise<SingleResponse<TenantInvoice>> {
177
+ return this.http.post<SingleResponse<TenantInvoice>>(
178
+ `/tenant/sub-tenants/${subTenantId}/incoming-invoices`,
179
+ params,
180
+ requestOptions
181
+ );
182
+ }
183
+
184
+ /**
185
+ * List incoming invoices for a sub-tenant
186
+ *
187
+ * Returns a paginated list of purchase invoices received by the sub-tenant.
188
+ *
189
+ * @param subTenantId - Sub-tenant UUID
190
+ * @param filters - Filter and pagination options
191
+ * @param requestOptions - Optional request configuration
192
+ * @returns Paginated list of invoices
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * // List all pending invoices
197
+ * const { data: invoices, meta } = await client.incomingInvoices.listForSubTenant(
198
+ * 'sub-tenant-uuid',
199
+ * { status: 'pending', per_page: 50 }
200
+ * );
201
+ *
202
+ * console.log(`Found ${meta.total} pending invoices to review`);
203
+ *
204
+ * // Filter by supplier
205
+ * const acmeInvoices = await client.incomingInvoices.listForSubTenant(
206
+ * 'sub-tenant-uuid',
207
+ * { seller_siret: '12345678901234' }
208
+ * );
209
+ * ```
210
+ */
211
+ async listForSubTenant(
212
+ subTenantId: string,
213
+ filters: TenantInvoiceFilters = {},
214
+ requestOptions?: RequestOptions
215
+ ): Promise<PaginatedResponse<TenantInvoice>> {
216
+ const query: Record<string, string | number | boolean | undefined> = {
217
+ ...filters,
218
+ status: Array.isArray(filters.status)
219
+ ? filters.status.join(',')
220
+ : filters.status,
221
+ };
222
+
223
+ return this.http.get<PaginatedResponse<TenantInvoice>>(
224
+ `/tenant/sub-tenants/${subTenantId}/incoming-invoices`,
225
+ query,
226
+ requestOptions
227
+ );
228
+ }
229
+
230
+ /**
231
+ * Get a specific incoming invoice by ID
232
+ *
233
+ * @param invoiceId - Invoice UUID
234
+ * @param requestOptions - Optional request configuration
235
+ * @returns Invoice details
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const { data: invoice } = await client.incomingInvoices.get('invoice-uuid');
240
+ *
241
+ * console.log('Invoice from:', invoice.seller.name);
242
+ * console.log('Status:', invoice.status);
243
+ * console.log('Amount:', invoice.total_ttc, invoice.currency);
244
+ * ```
245
+ */
246
+ async get(
247
+ invoiceId: string,
248
+ requestOptions?: RequestOptions
249
+ ): Promise<SingleResponse<TenantInvoice>> {
250
+ return this.http.get<SingleResponse<TenantInvoice>>(
251
+ `/tenant/incoming-invoices/${invoiceId}`,
252
+ undefined,
253
+ requestOptions
254
+ );
255
+ }
256
+
257
+ /**
258
+ * Accept an incoming invoice
259
+ *
260
+ * Marks the invoice as accepted, indicating approval for payment.
261
+ * Optionally specify an expected payment date.
262
+ *
263
+ * @param invoiceId - Invoice UUID
264
+ * @param input - Optional acceptance details
265
+ * @param requestOptions - Optional request configuration
266
+ * @returns Updated invoice
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * // Accept with payment date
271
+ * const { data: invoice } = await client.incomingInvoices.accept(
272
+ * 'invoice-uuid',
273
+ * {
274
+ * payment_date: '2026-02-15',
275
+ * note: 'Approved by CFO'
276
+ * }
277
+ * );
278
+ *
279
+ * console.log('Invoice accepted:', invoice.status); // 'accepted'
280
+ *
281
+ * // Simple acceptance
282
+ * await client.incomingInvoices.accept('invoice-uuid');
283
+ * ```
284
+ */
285
+ async accept(
286
+ invoiceId: string,
287
+ input?: AcceptIncomingInvoiceInput,
288
+ requestOptions?: RequestOptions
289
+ ): Promise<SingleResponse<TenantInvoice>> {
290
+ return this.http.post<SingleResponse<TenantInvoice>>(
291
+ `/tenant/incoming-invoices/${invoiceId}/accept`,
292
+ input,
293
+ requestOptions
294
+ );
295
+ }
296
+
297
+ /**
298
+ * Reject an incoming invoice
299
+ *
300
+ * Marks the invoice as rejected with a reason and optional code.
301
+ *
302
+ * @param invoiceId - Invoice UUID
303
+ * @param reason - Reason for rejection
304
+ * @param code - Optional standardized rejection code
305
+ * @param requestOptions - Optional request configuration
306
+ * @returns Updated invoice
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * const { data: invoice } = await client.incomingInvoices.reject(
311
+ * 'invoice-uuid',
312
+ * 'Amount does not match purchase order PO-2026-042',
313
+ * 'incorrect_amount'
314
+ * );
315
+ *
316
+ * console.log('Invoice rejected:', invoice.status); // 'rejected'
317
+ * ```
318
+ */
319
+ async reject(
320
+ invoiceId: string,
321
+ reason: string,
322
+ code?: RejectionCode,
323
+ requestOptions?: RequestOptions
324
+ ): Promise<SingleResponse<TenantInvoice>> {
325
+ const input: RejectIncomingInvoiceInput = { reason };
326
+ if (code) {
327
+ input.reason_code = code;
328
+ }
329
+
330
+ return this.http.post<SingleResponse<TenantInvoice>>(
331
+ `/tenant/incoming-invoices/${invoiceId}/reject`,
332
+ input,
333
+ requestOptions
334
+ );
335
+ }
336
+
337
+ /**
338
+ * Mark an incoming invoice as paid
339
+ *
340
+ * Records payment information for an accepted invoice.
341
+ * This is a mandatory step in the French e-invoicing lifecycle.
342
+ *
343
+ * @param invoiceId - Invoice UUID
344
+ * @param input - Optional payment details
345
+ * @param requestOptions - Optional request configuration
346
+ * @returns Updated invoice with payment information
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * // Mark as paid with details
351
+ * const { data: invoice } = await client.incomingInvoices.markPaid(
352
+ * 'invoice-uuid',
353
+ * {
354
+ * payment_reference: 'VIR-2026-0150',
355
+ * paid_at: '2026-02-14T14:30:00Z',
356
+ * note: 'Payment via bank transfer'
357
+ * }
358
+ * );
359
+ *
360
+ * console.log('Invoice paid:', invoice.status); // 'paid'
361
+ * console.log('Payment ref:', invoice.payment_reference);
362
+ *
363
+ * // Simple mark as paid (current date)
364
+ * await client.incomingInvoices.markPaid('invoice-uuid');
365
+ * ```
366
+ */
367
+ async markPaid(
368
+ invoiceId: string,
369
+ input?: MarkPaidIncomingInvoiceInput,
370
+ requestOptions?: RequestOptions
371
+ ): Promise<SingleResponse<TenantInvoice>> {
372
+ return this.http.post<SingleResponse<TenantInvoice>>(
373
+ `/tenant/incoming-invoices/${invoiceId}/mark-paid`,
374
+ input,
375
+ requestOptions
376
+ );
377
+ }
378
+
379
+ /**
380
+ * Delete an incoming invoice
381
+ *
382
+ * Only invoices in 'pending' status can be deleted.
383
+ *
384
+ * @param invoiceId - Invoice UUID
385
+ * @param requestOptions - Optional request configuration
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * await client.incomingInvoices.delete('pending-invoice-uuid');
390
+ * console.log('Incoming invoice deleted');
391
+ * ```
392
+ */
393
+ async delete(
394
+ invoiceId: string,
395
+ requestOptions?: RequestOptions
396
+ ): Promise<MessageResponse> {
397
+ return this.http.delete<MessageResponse>(
398
+ `/tenant/incoming-invoices/${invoiceId}`,
399
+ requestOptions
400
+ );
401
+ }
402
+
403
+ /**
404
+ * Download incoming invoice as PDF
405
+ *
406
+ * @param invoiceId - Invoice UUID
407
+ * @param requestOptions - Optional request configuration
408
+ * @returns ArrayBuffer containing the PDF file
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * const pdfBuffer = await client.incomingInvoices.download('invoice-uuid');
413
+ *
414
+ * // Save to file (Node.js)
415
+ * import { writeFileSync } from 'fs';
416
+ * writeFileSync('supplier-invoice.pdf', Buffer.from(pdfBuffer));
417
+ * ```
418
+ */
419
+ async download(
420
+ invoiceId: string,
421
+ requestOptions?: RequestOptions
422
+ ): Promise<ArrayBuffer> {
423
+ return this.http.getRaw(
424
+ `/tenant/incoming-invoices/${invoiceId}/download`,
425
+ undefined,
426
+ requestOptions
427
+ );
428
+ }
429
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Scell Tenant Client
3
+ *
4
+ * Client for multi-tenant operations using X-Tenant-Key authentication.
5
+ * Use this client for tenant-specific invoice and credit note operations.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import { HttpClient, type ClientConfig, type RequestOptions } from './client.js';
11
+ import { TenantDirectInvoicesResource } from './resources/tenant-direct-invoices.js';
12
+ import { TenantDirectCreditNotesResource } from './resources/tenant-direct-credit-notes.js';
13
+ import { TenantIncomingInvoicesResource } from './resources/tenant-incoming-invoices.js';
14
+ import { TenantCreditNotesResource } from './resources/tenant-credit-notes.js';
15
+ import { FiscalResource } from './resources/fiscal.js';
16
+ import { BillingResource } from './resources/billing.js';
17
+ import { StatsResource } from './resources/stats.js';
18
+ import { SubTenantsResource } from './resources/sub-tenants.js';
19
+ import type { SingleResponse } from './types/common.js';
20
+ import type {
21
+ TenantProfile,
22
+ UpdateTenantProfileInput,
23
+ TenantBalance,
24
+ TenantQuickStats,
25
+ RegenerateKeyResult,
26
+ } from './types/tenant-profile.js';
27
+
28
+ /**
29
+ * Scell Tenant Client
30
+ *
31
+ * Use this client for multi-tenant operations with X-Tenant-Key authentication.
32
+ */
33
+ export class ScellTenantClient {
34
+ private readonly http: HttpClient;
35
+
36
+ /** Direct invoices resource */
37
+ public readonly directInvoices: TenantDirectInvoicesResource;
38
+
39
+ /** Direct credit notes resource */
40
+ public readonly directCreditNotes: TenantDirectCreditNotesResource;
41
+
42
+ /** Incoming invoices resource */
43
+ public readonly incomingInvoices: TenantIncomingInvoicesResource;
44
+
45
+ /** Sub-tenant credit notes resource */
46
+ public readonly subTenantCreditNotes: TenantCreditNotesResource;
47
+
48
+ /** Fiscal compliance resource (LF 2026) */
49
+ public readonly fiscal: FiscalResource;
50
+
51
+ /** Billing resource */
52
+ public readonly billing: BillingResource;
53
+
54
+ /** Stats resource */
55
+ public readonly stats: StatsResource;
56
+
57
+ /** Sub-tenants resource */
58
+ public readonly subTenants: SubTenantsResource;
59
+
60
+ /**
61
+ * Create a new Scell Tenant Client
62
+ *
63
+ * @param tenantKey - Your tenant API key (from dashboard)
64
+ * @param config - Optional client configuration
65
+ */
66
+ constructor(tenantKey: string, config: ClientConfig = {}) {
67
+ this.http = new HttpClient('tenant-key', tenantKey, config);
68
+
69
+ this.directInvoices = new TenantDirectInvoicesResource(this.http);
70
+ this.directCreditNotes = new TenantDirectCreditNotesResource(this.http);
71
+ this.incomingInvoices = new TenantIncomingInvoicesResource(this.http);
72
+ this.subTenantCreditNotes = new TenantCreditNotesResource(this.http);
73
+ this.fiscal = new FiscalResource(this.http);
74
+ this.billing = new BillingResource(this.http);
75
+ this.stats = new StatsResource(this.http);
76
+ this.subTenants = new SubTenantsResource(this.http);
77
+ }
78
+
79
+ // ── Tenant Profile Methods ──────────────────────────────
80
+
81
+ /** Get tenant profile */
82
+ async me(requestOptions?: RequestOptions): Promise<SingleResponse<TenantProfile>> {
83
+ return this.http.get<SingleResponse<TenantProfile>>('/tenant/me', undefined, requestOptions);
84
+ }
85
+
86
+ /** Update tenant profile */
87
+ async updateProfile(input: UpdateTenantProfileInput, requestOptions?: RequestOptions): Promise<SingleResponse<TenantProfile>> {
88
+ return this.http.post<SingleResponse<TenantProfile>>('/tenant/me', input, requestOptions);
89
+ }
90
+
91
+ /** Get tenant balance */
92
+ async balance(requestOptions?: RequestOptions): Promise<SingleResponse<TenantBalance>> {
93
+ return this.http.get<SingleResponse<TenantBalance>>('/tenant/balance', undefined, requestOptions);
94
+ }
95
+
96
+ /** Get quick stats */
97
+ async quickStats(requestOptions?: RequestOptions): Promise<SingleResponse<TenantQuickStats>> {
98
+ return this.http.get<SingleResponse<TenantQuickStats>>('/tenant/stats', undefined, requestOptions);
99
+ }
100
+
101
+ /** Regenerate tenant key */
102
+ async regenerateKey(requestOptions?: RequestOptions): Promise<SingleResponse<RegenerateKeyResult>> {
103
+ return this.http.post<SingleResponse<RegenerateKeyResult>>('/tenant/regenerate-key', undefined, requestOptions);
104
+ }
105
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Billing Types
3
+ *
4
+ * Types for the tenant billing API.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+
9
+ export interface BillingInvoice {
10
+ id: string;
11
+ invoice_number: string;
12
+ period: string;
13
+ total_ht: number;
14
+ total_tax: number;
15
+ total_ttc: number;
16
+ status: string;
17
+ currency: string;
18
+ issued_at?: string | null;
19
+ due_date?: string | null;
20
+ paid_at?: string | null;
21
+ lines?: BillingInvoiceLine[] | null;
22
+ }
23
+
24
+ export interface BillingInvoiceLine {
25
+ description: string;
26
+ quantity: number;
27
+ unit_price: number;
28
+ total: number;
29
+ }
30
+
31
+ export interface BillingInvoiceListOptions {
32
+ per_page?: number;
33
+ page?: number;
34
+ }
35
+
36
+ export interface BillingUsage {
37
+ period: string;
38
+ invoices_count: number;
39
+ credit_notes_count: number;
40
+ signatures_count: number;
41
+ total_cost: number;
42
+ currency: string;
43
+ breakdown?: Record<string, unknown> | null;
44
+ }
45
+
46
+ export interface BillingUsageOptions {
47
+ period?: string;
48
+ }
49
+
50
+ export interface BillingTopUpInput {
51
+ amount: number;
52
+ payment_method?: string;
53
+ }
54
+
55
+ export interface BillingTopUpConfirmInput {
56
+ payment_intent_id: string;
57
+ }
58
+
59
+ export interface BillingTransaction {
60
+ id: string;
61
+ type: string;
62
+ amount: number;
63
+ currency: string;
64
+ description?: string | null;
65
+ reference?: string | null;
66
+ status?: string | null;
67
+ created_at?: string | null;
68
+ }
69
+
70
+ export interface BillingTransactionListOptions {
71
+ per_page?: number;
72
+ page?: number;
73
+ }