tiime-cli 1.1.0 → 1.2.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 +1 -1
- package/dist/cli.js +856 -328
- package/dist/index.d.ts +53 -2
- package/dist/index.js +32 -0
- package/package.json +16 -14
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
-
import { defineCommand as
|
|
4
|
+
import { defineCommand as defineCommand15, renderUsage, runMain } from "citty";
|
|
5
5
|
|
|
6
|
-
// src/cli/commands/
|
|
7
|
-
import * as p from "@clack/prompts";
|
|
6
|
+
// src/cli/commands/audit.ts
|
|
8
7
|
import { defineCommand } from "citty";
|
|
8
|
+
import { consola as consola2 } from "consola";
|
|
9
|
+
|
|
10
|
+
// src/sdk/client.ts
|
|
11
|
+
import { ofetch as ofetch2 } from "ofetch";
|
|
9
12
|
|
|
10
13
|
// src/sdk/auth.ts
|
|
11
14
|
import { execSync } from "child_process";
|
|
@@ -166,10 +169,6 @@ var TokenManager = class {
|
|
|
166
169
|
}
|
|
167
170
|
};
|
|
168
171
|
|
|
169
|
-
// src/cli/output.ts
|
|
170
|
-
import Table from "cli-table3";
|
|
171
|
-
import { consola } from "consola";
|
|
172
|
-
|
|
173
172
|
// src/sdk/errors.ts
|
|
174
173
|
var TiimeError = class extends Error {
|
|
175
174
|
constructor(message, status, endpoint, details) {
|
|
@@ -190,239 +189,6 @@ var TiimeError = class extends Error {
|
|
|
190
189
|
}
|
|
191
190
|
};
|
|
192
191
|
|
|
193
|
-
// src/cli/output.ts
|
|
194
|
-
var formatArg = {
|
|
195
|
-
format: {
|
|
196
|
-
type: "string",
|
|
197
|
-
description: "Format de sortie (json, table, csv)",
|
|
198
|
-
default: "json"
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
var stringifyValue = (value) => {
|
|
202
|
-
if (value === null || value === void 0) return "";
|
|
203
|
-
if (typeof value === "object") return JSON.stringify(value);
|
|
204
|
-
return String(value);
|
|
205
|
-
};
|
|
206
|
-
var outputJson = (data) => {
|
|
207
|
-
process.stdout.write(`${JSON.stringify(data, null, 2)}
|
|
208
|
-
`);
|
|
209
|
-
};
|
|
210
|
-
var outputTable = (data) => {
|
|
211
|
-
if (Array.isArray(data) && data.length > 0 && typeof data[0] === "object" && data[0] !== null) {
|
|
212
|
-
const keys = Object.keys(data[0]);
|
|
213
|
-
const table = new Table({ head: keys });
|
|
214
|
-
for (const row of data) {
|
|
215
|
-
const record = row;
|
|
216
|
-
table.push(keys.map((key) => stringifyValue(record[key])));
|
|
217
|
-
}
|
|
218
|
-
process.stdout.write(`${table.toString()}
|
|
219
|
-
`);
|
|
220
|
-
} else if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
221
|
-
const table = new Table();
|
|
222
|
-
for (const [key, value] of Object.entries(
|
|
223
|
-
data
|
|
224
|
-
)) {
|
|
225
|
-
table.push({ [key]: stringifyValue(value) });
|
|
226
|
-
}
|
|
227
|
-
process.stdout.write(`${table.toString()}
|
|
228
|
-
`);
|
|
229
|
-
} else {
|
|
230
|
-
outputJson(data);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
var escapeCsvField = (value) => {
|
|
234
|
-
if (value.includes(",") || value.includes('"') || value.includes("\n")) {
|
|
235
|
-
return `"${value.replace(/"/g, '""')}"`;
|
|
236
|
-
}
|
|
237
|
-
return value;
|
|
238
|
-
};
|
|
239
|
-
var outputCsv = (data) => {
|
|
240
|
-
if (Array.isArray(data) && data.length > 0 && typeof data[0] === "object" && data[0] !== null) {
|
|
241
|
-
const keys = Object.keys(data[0]);
|
|
242
|
-
const header = keys.map(escapeCsvField).join(",");
|
|
243
|
-
const lines = data.map((row) => {
|
|
244
|
-
const record = row;
|
|
245
|
-
return keys.map((key) => escapeCsvField(stringifyValue(record[key]))).join(",");
|
|
246
|
-
});
|
|
247
|
-
process.stdout.write(`${header}
|
|
248
|
-
${lines.join("\n")}
|
|
249
|
-
`);
|
|
250
|
-
} else if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
251
|
-
const entries = Object.entries(data);
|
|
252
|
-
const header = "key,value";
|
|
253
|
-
const lines = entries.map(
|
|
254
|
-
([key, value]) => `${escapeCsvField(key)},${escapeCsvField(stringifyValue(value))}`
|
|
255
|
-
);
|
|
256
|
-
process.stdout.write(`${header}
|
|
257
|
-
${lines.join("\n")}
|
|
258
|
-
`);
|
|
259
|
-
} else {
|
|
260
|
-
outputJson(data);
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
var output = (data, options) => {
|
|
264
|
-
const format = options?.format ?? "json";
|
|
265
|
-
if (!["json", "table", "csv"].includes(format)) {
|
|
266
|
-
process.stderr.write(
|
|
267
|
-
`${JSON.stringify({ error: `Format invalide : "${format}". Utilisez json, table ou csv.` })}
|
|
268
|
-
`
|
|
269
|
-
);
|
|
270
|
-
process.exit(1);
|
|
271
|
-
}
|
|
272
|
-
switch (format) {
|
|
273
|
-
case "table":
|
|
274
|
-
outputTable(data);
|
|
275
|
-
break;
|
|
276
|
-
case "csv":
|
|
277
|
-
outputCsv(data);
|
|
278
|
-
break;
|
|
279
|
-
default:
|
|
280
|
-
outputJson(data);
|
|
281
|
-
break;
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
var outputColoredStatus = (data) => {
|
|
285
|
-
const {
|
|
286
|
-
company_id,
|
|
287
|
-
bank_accounts,
|
|
288
|
-
invoices,
|
|
289
|
-
pending_quotations,
|
|
290
|
-
total_clients,
|
|
291
|
-
unimputed_transactions
|
|
292
|
-
} = data;
|
|
293
|
-
console.error("");
|
|
294
|
-
console.error(` \u{1F4CA} R\xE9sum\xE9 \u2014 Entreprise #${company_id}`);
|
|
295
|
-
for (const a of bank_accounts) {
|
|
296
|
-
console.error(
|
|
297
|
-
` \u{1F4B0} Soldes : ${a.name} ${a.balance.toFixed(2)}${a.currency === "EUR" ? "\u20AC" : a.currency}`
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
console.error(
|
|
301
|
-
` \u{1F4C4} Factures : ${invoices.drafts} brouillon(s), ${invoices.unpaid} impay\xE9e(s)`
|
|
302
|
-
);
|
|
303
|
-
console.error(` \u{1F4CB} Devis en cours : ${pending_quotations}`);
|
|
304
|
-
console.error(` \u{1F465} Clients : ${total_clients}`);
|
|
305
|
-
if (unimputed_transactions > 0) {
|
|
306
|
-
console.error(` \u26A0\uFE0F Transactions non imput\xE9es : ${unimputed_transactions}`);
|
|
307
|
-
} else {
|
|
308
|
-
console.error(` \u2705 Toutes les transactions sont imput\xE9es`);
|
|
309
|
-
}
|
|
310
|
-
console.error("");
|
|
311
|
-
};
|
|
312
|
-
var outputError = (error) => {
|
|
313
|
-
if (error instanceof TiimeError) {
|
|
314
|
-
process.stderr.write(`${JSON.stringify(error.toJSON())}
|
|
315
|
-
`);
|
|
316
|
-
} else {
|
|
317
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
318
|
-
process.stderr.write(`${JSON.stringify({ error: message })}
|
|
319
|
-
`);
|
|
320
|
-
}
|
|
321
|
-
process.exit(1);
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// src/cli/commands/auth.ts
|
|
325
|
-
var authCommand = defineCommand({
|
|
326
|
-
meta: { name: "auth", description: "Gestion de l'authentification" },
|
|
327
|
-
subCommands: {
|
|
328
|
-
login: defineCommand({
|
|
329
|
-
meta: { name: "login", description: "Se connecter \xE0 Tiime" },
|
|
330
|
-
args: {
|
|
331
|
-
email: {
|
|
332
|
-
type: "string",
|
|
333
|
-
description: "Adresse email"
|
|
334
|
-
},
|
|
335
|
-
password: {
|
|
336
|
-
type: "string",
|
|
337
|
-
description: "Mot de passe"
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
async run({ args }) {
|
|
341
|
-
const hasArgs = args.email && args.password;
|
|
342
|
-
if (hasArgs) {
|
|
343
|
-
try {
|
|
344
|
-
const tm = new TokenManager();
|
|
345
|
-
await tm.login(args.email, args.password);
|
|
346
|
-
const info = tm.getTokenInfo();
|
|
347
|
-
output({
|
|
348
|
-
status: "authenticated",
|
|
349
|
-
email: info.email,
|
|
350
|
-
expires_at: info.expiresAt?.toISOString()
|
|
351
|
-
});
|
|
352
|
-
} catch (e) {
|
|
353
|
-
outputError(e);
|
|
354
|
-
}
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
p.intro("Connexion \xE0 Tiime");
|
|
358
|
-
const email = await p.text({
|
|
359
|
-
message: "Adresse email",
|
|
360
|
-
placeholder: "vous@example.com",
|
|
361
|
-
validate: (value) => {
|
|
362
|
-
if (!value || !value.includes("@")) return "Adresse email invalide";
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
if (p.isCancel(email)) {
|
|
366
|
-
p.cancel("Connexion annul\xE9e.");
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
const password2 = await p.password({
|
|
370
|
-
message: "Mot de passe",
|
|
371
|
-
validate: (value) => {
|
|
372
|
-
if (!value) return "Le mot de passe est requis";
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
if (p.isCancel(password2)) {
|
|
376
|
-
p.cancel("Connexion annul\xE9e.");
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
const s = p.spinner();
|
|
380
|
-
s.start("Authentification en cours...");
|
|
381
|
-
try {
|
|
382
|
-
const tm = new TokenManager();
|
|
383
|
-
await tm.login(email, password2);
|
|
384
|
-
const info = tm.getTokenInfo();
|
|
385
|
-
s.stop("Authentification r\xE9ussie");
|
|
386
|
-
p.outro(`Connect\xE9 en tant que ${info.email ?? email}`);
|
|
387
|
-
} catch (e) {
|
|
388
|
-
s.stop("Authentification \xE9chou\xE9e");
|
|
389
|
-
const message = e instanceof Error ? e.message : "Erreur inconnue";
|
|
390
|
-
p.cancel(message);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}),
|
|
394
|
-
logout: defineCommand({
|
|
395
|
-
meta: { name: "logout", description: "Se d\xE9connecter de Tiime" },
|
|
396
|
-
run() {
|
|
397
|
-
const tm = new TokenManager();
|
|
398
|
-
tm.logout();
|
|
399
|
-
output({ status: "logged_out" });
|
|
400
|
-
}
|
|
401
|
-
}),
|
|
402
|
-
status: defineCommand({
|
|
403
|
-
meta: {
|
|
404
|
-
name: "status",
|
|
405
|
-
description: "Afficher le statut d'authentification"
|
|
406
|
-
},
|
|
407
|
-
run() {
|
|
408
|
-
const tm = new TokenManager();
|
|
409
|
-
const info = tm.getTokenInfo();
|
|
410
|
-
output({
|
|
411
|
-
authenticated: tm.isAuthenticated(),
|
|
412
|
-
email: info.email,
|
|
413
|
-
expires_at: info.expiresAt?.toISOString() ?? null
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
})
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// src/cli/commands/bank.ts
|
|
421
|
-
import { defineCommand as defineCommand2 } from "citty";
|
|
422
|
-
|
|
423
|
-
// src/sdk/client.ts
|
|
424
|
-
import { ofetch as ofetch2 } from "ofetch";
|
|
425
|
-
|
|
426
192
|
// src/sdk/resources/bank-accounts.ts
|
|
427
193
|
var BankAccountsResource = class {
|
|
428
194
|
constructor(fetch, companyId) {
|
|
@@ -492,6 +258,30 @@ var BankTransactionsResource = class {
|
|
|
492
258
|
`/companies/${this.companyId}/bank_transactions/unimputed`
|
|
493
259
|
);
|
|
494
260
|
}
|
|
261
|
+
get(transactionId) {
|
|
262
|
+
return this.fetch(
|
|
263
|
+
`/companies/${this.companyId}/bank_transactions/${transactionId}`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
labelSuggestions(transactionId) {
|
|
267
|
+
return this.fetch(
|
|
268
|
+
`/companies/${this.companyId}/bank_transactions/${transactionId}/label_suggestions`,
|
|
269
|
+
{
|
|
270
|
+
headers: {
|
|
271
|
+
Accept: "application/vnd.tiime.bank_transactions.label_suggestions.v2+json"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
impute(transactionId, imputations) {
|
|
277
|
+
return this.fetch(
|
|
278
|
+
`/companies/${this.companyId}/bank_transactions/${transactionId}`,
|
|
279
|
+
{
|
|
280
|
+
method: "PATCH",
|
|
281
|
+
body: { imputations }
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
}
|
|
495
285
|
};
|
|
496
286
|
|
|
497
287
|
// src/sdk/resources/clients.ts
|
|
@@ -818,6 +608,14 @@ var QuotationsResource = class {
|
|
|
818
608
|
);
|
|
819
609
|
}
|
|
820
610
|
create(params) {
|
|
611
|
+
for (const line of params.lines ?? []) {
|
|
612
|
+
line.line_amount = line.quantity * line.unit_amount;
|
|
613
|
+
line.sequence ??= 1;
|
|
614
|
+
line.invoicing_category_type ??= "benefit";
|
|
615
|
+
line.discount_description ??= "";
|
|
616
|
+
line.discount_amount ??= null;
|
|
617
|
+
line.discount_percentage ??= null;
|
|
618
|
+
}
|
|
821
619
|
return this.fetch(`/companies/${this.companyId}/quotations`, {
|
|
822
620
|
method: "POST",
|
|
823
621
|
body: params
|
|
@@ -931,42 +729,594 @@ var TiimeClient = class {
|
|
|
931
729
|
}
|
|
932
730
|
};
|
|
933
731
|
|
|
934
|
-
// src/cli/
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
732
|
+
// src/cli/audit.ts
|
|
733
|
+
var log = (...args) => console.error(...args);
|
|
734
|
+
var batchAsync = async (items, batchSize, fn) => {
|
|
735
|
+
const results = [];
|
|
736
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
737
|
+
const batch = items.slice(i, i + batchSize);
|
|
738
|
+
const batchResults = await Promise.all(batch.map(fn));
|
|
739
|
+
results.push(...batchResults);
|
|
740
|
+
}
|
|
741
|
+
return results;
|
|
742
|
+
};
|
|
743
|
+
async function auditForCompany(client, companyId, companyName, options) {
|
|
744
|
+
const unimputedFindings = [];
|
|
745
|
+
const appliedImputations = [];
|
|
746
|
+
log(`[${companyName}] R\xE9cup\xE9ration des transactions non imput\xE9es...`);
|
|
747
|
+
const unimputedTxs = await client.bankTransactions.unimputed();
|
|
748
|
+
log(
|
|
749
|
+
`[${companyName}] ${unimputedTxs.length} non imput\xE9es, r\xE9cup\xE9ration des suggestions...`
|
|
750
|
+
);
|
|
751
|
+
const suggestions = await batchAsync(unimputedTxs, 5, async (tx) => {
|
|
752
|
+
try {
|
|
753
|
+
const fullTx = tx.wording !== void 0 ? tx : await client.bankTransactions.get(tx.id);
|
|
754
|
+
const sug = await client.bankTransactions.labelSuggestions(tx.id);
|
|
755
|
+
return { tx: fullTx, suggestion: sug[0] ?? null };
|
|
756
|
+
} catch (e) {
|
|
757
|
+
log(
|
|
758
|
+
`[${companyName}] Erreur pour tx #${tx.id}: ${e instanceof Error ? e.message : e}`
|
|
759
|
+
);
|
|
760
|
+
return { tx, suggestion: null };
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
for (const { tx, suggestion } of suggestions) {
|
|
764
|
+
unimputedFindings.push({
|
|
765
|
+
transaction_id: tx.id,
|
|
766
|
+
wording: tx.wording,
|
|
767
|
+
amount: tx.amount,
|
|
768
|
+
currency: tx.currency,
|
|
769
|
+
transaction_date: tx.transaction_date,
|
|
770
|
+
suggested_label_id: suggestion?.id ?? null,
|
|
771
|
+
suggested_label_name: suggestion ? suggestion.name ?? suggestion.label : null
|
|
772
|
+
});
|
|
773
|
+
if (options.apply && suggestion) {
|
|
774
|
+
const imputationLabel = {
|
|
775
|
+
...suggestion,
|
|
776
|
+
disabled: false
|
|
777
|
+
};
|
|
778
|
+
const imputationParams = [
|
|
779
|
+
{
|
|
780
|
+
label: imputationLabel,
|
|
781
|
+
amount: tx.amount,
|
|
782
|
+
documents: [],
|
|
783
|
+
accountant_detail_requests: []
|
|
784
|
+
}
|
|
785
|
+
];
|
|
786
|
+
try {
|
|
787
|
+
await client.bankTransactions.impute(tx.id, imputationParams);
|
|
788
|
+
appliedImputations.push({
|
|
789
|
+
transaction_id: tx.id,
|
|
790
|
+
wording: tx.wording,
|
|
791
|
+
amount: tx.amount,
|
|
792
|
+
label_name: suggestion.name ?? suggestion.label,
|
|
793
|
+
status: "applied"
|
|
794
|
+
});
|
|
795
|
+
} catch {
|
|
796
|
+
appliedImputations.push({
|
|
797
|
+
transaction_id: tx.id,
|
|
798
|
+
wording: tx.wording,
|
|
799
|
+
amount: tx.amount,
|
|
800
|
+
label_name: suggestion.name ?? suggestion.label,
|
|
801
|
+
status: "error"
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
let from;
|
|
807
|
+
let to;
|
|
808
|
+
try {
|
|
809
|
+
const period = await client.company.accountingPeriod();
|
|
810
|
+
from = period.start_date;
|
|
811
|
+
to = period.end_date;
|
|
812
|
+
} catch {
|
|
813
|
+
const now = /* @__PURE__ */ new Date();
|
|
814
|
+
from = `${now.getFullYear()}-01-01`;
|
|
815
|
+
to = now.toISOString().slice(0, 10);
|
|
816
|
+
}
|
|
817
|
+
const missingDocuments = [];
|
|
818
|
+
const appliedIds = new Set(
|
|
819
|
+
appliedImputations.filter((a) => a.status === "applied").map((a) => a.transaction_id)
|
|
820
|
+
);
|
|
821
|
+
log(
|
|
822
|
+
`[${companyName}] V\xE9rification des documents manquants (${from} \u2192 ${to})...`
|
|
823
|
+
);
|
|
824
|
+
const allTransactions = await client.bankTransactions.listAll({ from, to });
|
|
825
|
+
for (const tx of allTransactions) {
|
|
826
|
+
if (tx.imputations.length === 0) continue;
|
|
827
|
+
if (appliedIds.has(tx.id)) continue;
|
|
828
|
+
const allEmpty = tx.imputations.every(
|
|
829
|
+
(imp) => imp.count_documents === 0 && imp.count_invoices === 0
|
|
830
|
+
);
|
|
831
|
+
if (allEmpty) {
|
|
832
|
+
missingDocuments.push({
|
|
833
|
+
transaction_id: tx.id,
|
|
834
|
+
wording: tx.wording,
|
|
835
|
+
amount: tx.amount,
|
|
836
|
+
currency: tx.currency,
|
|
837
|
+
transaction_date: tx.transaction_date,
|
|
838
|
+
operation_type: tx.operation_type,
|
|
839
|
+
label_name: tx.imputations[0].label.name ?? tx.imputations[0].label.label
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const withSuggestions = unimputedFindings.filter(
|
|
844
|
+
(f) => f.suggested_label_id !== null
|
|
845
|
+
).length;
|
|
846
|
+
return {
|
|
847
|
+
company_id: companyId,
|
|
848
|
+
company_name: companyName,
|
|
849
|
+
error: null,
|
|
850
|
+
unimputed_transactions: unimputedFindings,
|
|
851
|
+
missing_documents: missingDocuments,
|
|
852
|
+
applied_imputations: appliedImputations,
|
|
853
|
+
summary: {
|
|
854
|
+
total_unimputed: unimputedFindings.length,
|
|
855
|
+
total_unimputed_amount: unimputedFindings.reduce(
|
|
856
|
+
(sum, f) => sum + Math.abs(f.amount),
|
|
857
|
+
0
|
|
858
|
+
),
|
|
859
|
+
with_suggestions: withSuggestions,
|
|
860
|
+
without_suggestions: unimputedFindings.length - withSuggestions,
|
|
861
|
+
total_missing_documents: missingDocuments.length,
|
|
862
|
+
total_missing_documents_amount: missingDocuments.reduce(
|
|
863
|
+
(sum, f) => sum + Math.abs(f.amount),
|
|
864
|
+
0
|
|
865
|
+
),
|
|
866
|
+
applied_count: appliedImputations.filter((a) => a.status === "applied").length
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
function emptyReport(companyId, companyName, error) {
|
|
871
|
+
return {
|
|
872
|
+
company_id: companyId,
|
|
873
|
+
company_name: companyName,
|
|
874
|
+
error,
|
|
875
|
+
unimputed_transactions: [],
|
|
876
|
+
missing_documents: [],
|
|
877
|
+
applied_imputations: [],
|
|
878
|
+
summary: {
|
|
879
|
+
total_unimputed: 0,
|
|
880
|
+
total_unimputed_amount: 0,
|
|
881
|
+
with_suggestions: 0,
|
|
882
|
+
without_suggestions: 0,
|
|
883
|
+
total_missing_documents: 0,
|
|
884
|
+
total_missing_documents_amount: 0,
|
|
885
|
+
applied_count: 0
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// src/cli/auto-impute.ts
|
|
891
|
+
async function autoImputeForCompany(client, companyId, companyName, options) {
|
|
892
|
+
const proposals = [];
|
|
893
|
+
const transactions = await client.bankTransactions.unimputed();
|
|
894
|
+
for (const tx of transactions) {
|
|
895
|
+
const suggestions = await client.bankTransactions.labelSuggestions(tx.id);
|
|
896
|
+
const firstSuggestion = suggestions[0];
|
|
897
|
+
if (!firstSuggestion) {
|
|
898
|
+
proposals.push({
|
|
899
|
+
company_id: companyId,
|
|
900
|
+
company_name: companyName,
|
|
901
|
+
transaction_id: tx.id,
|
|
902
|
+
wording: tx.wording,
|
|
903
|
+
amount: tx.amount,
|
|
904
|
+
currency: tx.currency,
|
|
905
|
+
suggested_label_id: 0,
|
|
906
|
+
suggested_label_name: "(aucune suggestion)",
|
|
907
|
+
status: "skipped"
|
|
908
|
+
});
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
if (!options.apply) {
|
|
912
|
+
proposals.push({
|
|
913
|
+
company_id: companyId,
|
|
914
|
+
company_name: companyName,
|
|
915
|
+
transaction_id: tx.id,
|
|
916
|
+
wording: tx.wording,
|
|
917
|
+
amount: tx.amount,
|
|
918
|
+
currency: tx.currency,
|
|
919
|
+
suggested_label_id: firstSuggestion.id,
|
|
920
|
+
suggested_label_name: firstSuggestion.name ?? firstSuggestion.label,
|
|
921
|
+
status: "proposed"
|
|
922
|
+
});
|
|
923
|
+
} else {
|
|
924
|
+
const imputationLabel = {
|
|
925
|
+
...firstSuggestion,
|
|
926
|
+
disabled: false
|
|
927
|
+
};
|
|
928
|
+
const imputationParams = [
|
|
929
|
+
{
|
|
930
|
+
label: imputationLabel,
|
|
931
|
+
amount: tx.amount,
|
|
932
|
+
documents: [],
|
|
933
|
+
accountant_detail_requests: []
|
|
934
|
+
}
|
|
935
|
+
];
|
|
936
|
+
try {
|
|
937
|
+
await client.bankTransactions.impute(tx.id, imputationParams);
|
|
938
|
+
proposals.push({
|
|
939
|
+
company_id: companyId,
|
|
940
|
+
company_name: companyName,
|
|
941
|
+
transaction_id: tx.id,
|
|
942
|
+
wording: tx.wording,
|
|
943
|
+
amount: tx.amount,
|
|
944
|
+
currency: tx.currency,
|
|
945
|
+
suggested_label_id: firstSuggestion.id,
|
|
946
|
+
suggested_label_name: firstSuggestion.name ?? firstSuggestion.label,
|
|
947
|
+
status: "applied"
|
|
948
|
+
});
|
|
949
|
+
} catch {
|
|
950
|
+
proposals.push({
|
|
951
|
+
company_id: companyId,
|
|
952
|
+
company_name: companyName,
|
|
953
|
+
transaction_id: tx.id,
|
|
954
|
+
wording: tx.wording,
|
|
955
|
+
amount: tx.amount,
|
|
956
|
+
currency: tx.currency,
|
|
957
|
+
suggested_label_id: firstSuggestion.id,
|
|
958
|
+
suggested_label_name: firstSuggestion.name ?? firstSuggestion.label,
|
|
959
|
+
status: "error"
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
return proposals;
|
|
965
|
+
}
|
|
966
|
+
function resolveCompanyIds(parts, companies) {
|
|
967
|
+
return parts.map((p2) => {
|
|
968
|
+
if (/^\d+$/.test(p2)) return Number(p2);
|
|
969
|
+
const match = companies.find(
|
|
970
|
+
(c) => c.name.toLowerCase() === p2.toLowerCase()
|
|
971
|
+
);
|
|
972
|
+
if (!match) throw new Error(`Entreprise introuvable : "${p2}"`);
|
|
973
|
+
return match.id;
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/cli/config.ts
|
|
978
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
979
|
+
import { homedir as homedir2 } from "os";
|
|
980
|
+
import { join as join2 } from "path";
|
|
981
|
+
var CONFIG_DIR2 = join2(homedir2(), ".config", "tiime");
|
|
982
|
+
var CONFIG_FILE = join2(CONFIG_DIR2, "config.json");
|
|
983
|
+
var loadConfig = () => {
|
|
984
|
+
try {
|
|
985
|
+
if (existsSync2(CONFIG_FILE)) {
|
|
986
|
+
return JSON.parse(readFileSync2(CONFIG_FILE, "utf-8"));
|
|
987
|
+
}
|
|
988
|
+
} catch {
|
|
989
|
+
}
|
|
990
|
+
return {};
|
|
991
|
+
};
|
|
992
|
+
var saveConfig = (config) => {
|
|
993
|
+
if (!existsSync2(CONFIG_DIR2)) {
|
|
994
|
+
mkdirSync2(CONFIG_DIR2, { recursive: true });
|
|
995
|
+
}
|
|
996
|
+
writeFileSync2(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
997
|
+
};
|
|
998
|
+
var getCompanyId = () => {
|
|
999
|
+
const config = loadConfig();
|
|
1000
|
+
if (!config.companyId) {
|
|
1001
|
+
throw new Error(
|
|
1002
|
+
"Aucune entreprise configur\xE9e. Ex\xE9cutez `tiime company use <id>` d'abord."
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
return config.companyId;
|
|
1006
|
+
};
|
|
1007
|
+
|
|
1008
|
+
// src/cli/output.ts
|
|
1009
|
+
import Table from "cli-table3";
|
|
1010
|
+
import { consola } from "consola";
|
|
1011
|
+
var formatArg = {
|
|
1012
|
+
format: {
|
|
1013
|
+
type: "string",
|
|
1014
|
+
description: "Format de sortie (json, table, csv)",
|
|
1015
|
+
default: "json"
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
var stringifyValue = (value) => {
|
|
1019
|
+
if (value === null || value === void 0) return "";
|
|
1020
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
1021
|
+
return String(value);
|
|
1022
|
+
};
|
|
1023
|
+
var outputJson = (data) => {
|
|
1024
|
+
process.stdout.write(`${JSON.stringify(data, null, 2)}
|
|
1025
|
+
`);
|
|
1026
|
+
};
|
|
1027
|
+
var outputTable = (data) => {
|
|
1028
|
+
if (Array.isArray(data) && data.length > 0 && typeof data[0] === "object" && data[0] !== null) {
|
|
1029
|
+
const keys = Object.keys(data[0]);
|
|
1030
|
+
const table = new Table({ head: keys });
|
|
1031
|
+
for (const row of data) {
|
|
1032
|
+
const record = row;
|
|
1033
|
+
table.push(keys.map((key) => stringifyValue(record[key])));
|
|
1034
|
+
}
|
|
1035
|
+
process.stdout.write(`${table.toString()}
|
|
1036
|
+
`);
|
|
1037
|
+
} else if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
1038
|
+
const table = new Table();
|
|
1039
|
+
for (const [key, value] of Object.entries(
|
|
1040
|
+
data
|
|
1041
|
+
)) {
|
|
1042
|
+
table.push({ [key]: stringifyValue(value) });
|
|
1043
|
+
}
|
|
1044
|
+
process.stdout.write(`${table.toString()}
|
|
1045
|
+
`);
|
|
1046
|
+
} else {
|
|
1047
|
+
outputJson(data);
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
var escapeCsvField = (value) => {
|
|
1051
|
+
if (value.includes(",") || value.includes('"') || value.includes("\n")) {
|
|
1052
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
1053
|
+
}
|
|
1054
|
+
return value;
|
|
1055
|
+
};
|
|
1056
|
+
var outputCsv = (data) => {
|
|
1057
|
+
if (Array.isArray(data) && data.length > 0 && typeof data[0] === "object" && data[0] !== null) {
|
|
1058
|
+
const keys = Object.keys(data[0]);
|
|
1059
|
+
const header = keys.map(escapeCsvField).join(",");
|
|
1060
|
+
const lines = data.map((row) => {
|
|
1061
|
+
const record = row;
|
|
1062
|
+
return keys.map((key) => escapeCsvField(stringifyValue(record[key]))).join(",");
|
|
1063
|
+
});
|
|
1064
|
+
process.stdout.write(`${header}
|
|
1065
|
+
${lines.join("\n")}
|
|
1066
|
+
`);
|
|
1067
|
+
} else if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
1068
|
+
const entries = Object.entries(data);
|
|
1069
|
+
const header = "key,value";
|
|
1070
|
+
const lines = entries.map(
|
|
1071
|
+
([key, value]) => `${escapeCsvField(key)},${escapeCsvField(stringifyValue(value))}`
|
|
1072
|
+
);
|
|
1073
|
+
process.stdout.write(`${header}
|
|
1074
|
+
${lines.join("\n")}
|
|
1075
|
+
`);
|
|
1076
|
+
} else {
|
|
1077
|
+
outputJson(data);
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
var output = (data, options) => {
|
|
1081
|
+
const format = options?.format ?? "json";
|
|
1082
|
+
if (!["json", "table", "csv"].includes(format)) {
|
|
1083
|
+
process.stderr.write(
|
|
1084
|
+
`${JSON.stringify({ error: `Format invalide : "${format}". Utilisez json, table ou csv.` })}
|
|
1085
|
+
`
|
|
1086
|
+
);
|
|
1087
|
+
process.exit(1);
|
|
1088
|
+
}
|
|
1089
|
+
switch (format) {
|
|
1090
|
+
case "table":
|
|
1091
|
+
outputTable(data);
|
|
1092
|
+
break;
|
|
1093
|
+
case "csv":
|
|
1094
|
+
outputCsv(data);
|
|
1095
|
+
break;
|
|
1096
|
+
default:
|
|
1097
|
+
outputJson(data);
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
var outputColoredStatus = (data) => {
|
|
1102
|
+
const {
|
|
1103
|
+
company_id,
|
|
1104
|
+
bank_accounts,
|
|
1105
|
+
invoices,
|
|
1106
|
+
pending_quotations,
|
|
1107
|
+
total_clients,
|
|
1108
|
+
unimputed_transactions
|
|
1109
|
+
} = data;
|
|
1110
|
+
console.error("");
|
|
1111
|
+
console.error(` \u{1F4CA} R\xE9sum\xE9 \u2014 Entreprise #${company_id}`);
|
|
1112
|
+
for (const a of bank_accounts) {
|
|
1113
|
+
console.error(
|
|
1114
|
+
` \u{1F4B0} Soldes : ${a.name} ${a.balance.toFixed(2)}${a.currency === "EUR" ? "\u20AC" : a.currency}`
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
console.error(
|
|
1118
|
+
` \u{1F4C4} Factures : ${invoices.drafts} brouillon(s), ${invoices.unpaid} impay\xE9e(s)`
|
|
1119
|
+
);
|
|
1120
|
+
console.error(` \u{1F4CB} Devis en cours : ${pending_quotations}`);
|
|
1121
|
+
console.error(` \u{1F465} Clients : ${total_clients}`);
|
|
1122
|
+
if (unimputed_transactions > 0) {
|
|
1123
|
+
console.error(` \u26A0\uFE0F Transactions non imput\xE9es : ${unimputed_transactions}`);
|
|
1124
|
+
} else {
|
|
1125
|
+
console.error(` \u2705 Toutes les transactions sont imput\xE9es`);
|
|
1126
|
+
}
|
|
1127
|
+
console.error("");
|
|
1128
|
+
};
|
|
1129
|
+
var outputError = (error) => {
|
|
1130
|
+
if (error instanceof TiimeError) {
|
|
1131
|
+
process.stderr.write(`${JSON.stringify(error.toJSON())}
|
|
1132
|
+
`);
|
|
1133
|
+
} else {
|
|
1134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1135
|
+
process.stderr.write(`${JSON.stringify({ error: message })}
|
|
1136
|
+
`);
|
|
1137
|
+
}
|
|
1138
|
+
process.exit(1);
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1141
|
+
// src/cli/commands/audit.ts
|
|
1142
|
+
var auditCommand = defineCommand({
|
|
1143
|
+
meta: {
|
|
1144
|
+
name: "audit",
|
|
1145
|
+
description: "Audit comptable multi-entreprises"
|
|
1146
|
+
},
|
|
1147
|
+
args: {
|
|
1148
|
+
"all-companies": {
|
|
1149
|
+
type: "boolean",
|
|
1150
|
+
description: "Traiter toutes les entreprises",
|
|
1151
|
+
default: false
|
|
1152
|
+
},
|
|
1153
|
+
company: {
|
|
1154
|
+
type: "string",
|
|
1155
|
+
description: "Entreprise(s) cible(s) (ID ou nom, s\xE9par\xE9s par des virgules)"
|
|
1156
|
+
},
|
|
1157
|
+
apply: {
|
|
1158
|
+
type: "boolean",
|
|
1159
|
+
description: "Appliquer les corrections automatiques (imputation auto)",
|
|
1160
|
+
default: false
|
|
1161
|
+
},
|
|
1162
|
+
...formatArg
|
|
1163
|
+
},
|
|
1164
|
+
async run({ args }) {
|
|
1165
|
+
try {
|
|
1166
|
+
let companyIds;
|
|
1167
|
+
if (args["all-companies"]) {
|
|
1168
|
+
const rootClient = new TiimeClient({ companyId: 0 });
|
|
1169
|
+
const companies = await rootClient.listCompanies();
|
|
1170
|
+
companyIds = companies.map((c) => c.id);
|
|
1171
|
+
} else if (args.company) {
|
|
1172
|
+
const parts = args.company.split(",").map((s) => s.trim());
|
|
1173
|
+
const allNumeric = parts.every((p2) => /^\d+$/.test(p2));
|
|
1174
|
+
if (allNumeric) {
|
|
1175
|
+
companyIds = parts.map(Number);
|
|
1176
|
+
} else {
|
|
1177
|
+
const rootClient = new TiimeClient({ companyId: 0 });
|
|
1178
|
+
const companies = await rootClient.listCompanies();
|
|
1179
|
+
companyIds = resolveCompanyIds(parts, companies);
|
|
1180
|
+
}
|
|
1181
|
+
} else {
|
|
1182
|
+
companyIds = [getCompanyId()];
|
|
1183
|
+
}
|
|
1184
|
+
const companyReports = [];
|
|
1185
|
+
for (const companyId of companyIds) {
|
|
1186
|
+
const client = new TiimeClient({ companyId });
|
|
1187
|
+
let companyName = String(companyId);
|
|
1188
|
+
try {
|
|
1189
|
+
const info = await client.company.get();
|
|
1190
|
+
companyName = info.name ?? String(companyId);
|
|
1191
|
+
} catch {
|
|
1192
|
+
}
|
|
1193
|
+
try {
|
|
1194
|
+
const report2 = await auditForCompany(client, companyId, companyName, {
|
|
1195
|
+
apply: args.apply
|
|
1196
|
+
});
|
|
1197
|
+
companyReports.push(report2);
|
|
1198
|
+
} catch (e) {
|
|
1199
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1200
|
+
consola2.error(`Erreur audit entreprise ${companyName}: ${message}`);
|
|
1201
|
+
companyReports.push(emptyReport(companyId, companyName, message));
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
const report = {
|
|
1205
|
+
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1206
|
+
companies: companyReports,
|
|
1207
|
+
apply_mode: args.apply
|
|
1208
|
+
};
|
|
1209
|
+
output(report, { format: args.format });
|
|
1210
|
+
} catch (e) {
|
|
1211
|
+
outputError(e);
|
|
944
1212
|
}
|
|
945
|
-
} catch {
|
|
946
|
-
}
|
|
947
|
-
return {};
|
|
948
|
-
};
|
|
949
|
-
var saveConfig = (config) => {
|
|
950
|
-
if (!existsSync2(CONFIG_DIR2)) {
|
|
951
|
-
mkdirSync2(CONFIG_DIR2, { recursive: true });
|
|
952
1213
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
// src/cli/commands/auth.ts
|
|
1217
|
+
import * as p from "@clack/prompts";
|
|
1218
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
1219
|
+
var authCommand = defineCommand2({
|
|
1220
|
+
meta: { name: "auth", description: "Gestion de l'authentification" },
|
|
1221
|
+
subCommands: {
|
|
1222
|
+
login: defineCommand2({
|
|
1223
|
+
meta: { name: "login", description: "Se connecter \xE0 Tiime" },
|
|
1224
|
+
args: {
|
|
1225
|
+
email: {
|
|
1226
|
+
type: "string",
|
|
1227
|
+
description: "Adresse email"
|
|
1228
|
+
},
|
|
1229
|
+
password: {
|
|
1230
|
+
type: "string",
|
|
1231
|
+
description: "Mot de passe"
|
|
1232
|
+
}
|
|
1233
|
+
},
|
|
1234
|
+
async run({ args }) {
|
|
1235
|
+
const hasArgs = args.email && args.password;
|
|
1236
|
+
if (hasArgs) {
|
|
1237
|
+
try {
|
|
1238
|
+
const tm = new TokenManager();
|
|
1239
|
+
await tm.login(args.email, args.password);
|
|
1240
|
+
const info = tm.getTokenInfo();
|
|
1241
|
+
output({
|
|
1242
|
+
status: "authenticated",
|
|
1243
|
+
email: info.email,
|
|
1244
|
+
expires_at: info.expiresAt?.toISOString()
|
|
1245
|
+
});
|
|
1246
|
+
} catch (e) {
|
|
1247
|
+
outputError(e);
|
|
1248
|
+
}
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
p.intro("Connexion \xE0 Tiime");
|
|
1252
|
+
const email = await p.text({
|
|
1253
|
+
message: "Adresse email",
|
|
1254
|
+
placeholder: "vous@example.com",
|
|
1255
|
+
validate: (value) => {
|
|
1256
|
+
if (!value || !value.includes("@")) return "Adresse email invalide";
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
if (p.isCancel(email)) {
|
|
1260
|
+
p.cancel("Connexion annul\xE9e.");
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
const password2 = await p.password({
|
|
1264
|
+
message: "Mot de passe",
|
|
1265
|
+
validate: (value) => {
|
|
1266
|
+
if (!value) return "Le mot de passe est requis";
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
if (p.isCancel(password2)) {
|
|
1270
|
+
p.cancel("Connexion annul\xE9e.");
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
const s = p.spinner();
|
|
1274
|
+
s.start("Authentification en cours...");
|
|
1275
|
+
try {
|
|
1276
|
+
const tm = new TokenManager();
|
|
1277
|
+
await tm.login(email, password2);
|
|
1278
|
+
const info = tm.getTokenInfo();
|
|
1279
|
+
s.stop("Authentification r\xE9ussie");
|
|
1280
|
+
p.outro(`Connect\xE9 en tant que ${info.email ?? email}`);
|
|
1281
|
+
} catch (e) {
|
|
1282
|
+
s.stop("Authentification \xE9chou\xE9e");
|
|
1283
|
+
const message = e instanceof Error ? e.message : "Erreur inconnue";
|
|
1284
|
+
p.cancel(message);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}),
|
|
1288
|
+
logout: defineCommand2({
|
|
1289
|
+
meta: { name: "logout", description: "Se d\xE9connecter de Tiime" },
|
|
1290
|
+
run() {
|
|
1291
|
+
const tm = new TokenManager();
|
|
1292
|
+
tm.logout();
|
|
1293
|
+
output({ status: "logged_out" });
|
|
1294
|
+
}
|
|
1295
|
+
}),
|
|
1296
|
+
status: defineCommand2({
|
|
1297
|
+
meta: {
|
|
1298
|
+
name: "status",
|
|
1299
|
+
description: "Afficher le statut d'authentification"
|
|
1300
|
+
},
|
|
1301
|
+
run() {
|
|
1302
|
+
const tm = new TokenManager();
|
|
1303
|
+
const info = tm.getTokenInfo();
|
|
1304
|
+
output({
|
|
1305
|
+
authenticated: tm.isAuthenticated(),
|
|
1306
|
+
email: info.email,
|
|
1307
|
+
expires_at: info.expiresAt?.toISOString() ?? null
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
})
|
|
961
1311
|
}
|
|
962
|
-
|
|
963
|
-
};
|
|
1312
|
+
});
|
|
964
1313
|
|
|
965
1314
|
// src/cli/commands/bank.ts
|
|
966
|
-
|
|
1315
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
1316
|
+
var bankCommand = defineCommand3({
|
|
967
1317
|
meta: { name: "bank", description: "Comptes bancaires et transactions" },
|
|
968
1318
|
subCommands: {
|
|
969
|
-
balance:
|
|
1319
|
+
balance: defineCommand3({
|
|
970
1320
|
meta: {
|
|
971
1321
|
name: "balance",
|
|
972
1322
|
description: "Afficher les soldes des comptes"
|
|
@@ -982,7 +1332,7 @@ var bankCommand = defineCommand2({
|
|
|
982
1332
|
}
|
|
983
1333
|
}
|
|
984
1334
|
}),
|
|
985
|
-
accounts:
|
|
1335
|
+
accounts: defineCommand3({
|
|
986
1336
|
meta: { name: "accounts", description: "Lister les comptes bancaires" },
|
|
987
1337
|
args: {
|
|
988
1338
|
...formatArg,
|
|
@@ -1002,7 +1352,7 @@ var bankCommand = defineCommand2({
|
|
|
1002
1352
|
}
|
|
1003
1353
|
}
|
|
1004
1354
|
}),
|
|
1005
|
-
transactions:
|
|
1355
|
+
transactions: defineCommand3({
|
|
1006
1356
|
meta: {
|
|
1007
1357
|
name: "transactions",
|
|
1008
1358
|
description: "Lister les transactions bancaires"
|
|
@@ -1074,7 +1424,7 @@ var bankCommand = defineCommand2({
|
|
|
1074
1424
|
}
|
|
1075
1425
|
}
|
|
1076
1426
|
}),
|
|
1077
|
-
unimputed:
|
|
1427
|
+
unimputed: defineCommand3({
|
|
1078
1428
|
meta: {
|
|
1079
1429
|
name: "unimputed",
|
|
1080
1430
|
description: "Transactions non imput\xE9es"
|
|
@@ -1089,16 +1439,189 @@ var bankCommand = defineCommand2({
|
|
|
1089
1439
|
outputError(e);
|
|
1090
1440
|
}
|
|
1091
1441
|
}
|
|
1442
|
+
}),
|
|
1443
|
+
impute: defineCommand3({
|
|
1444
|
+
meta: {
|
|
1445
|
+
name: "impute",
|
|
1446
|
+
description: "Imputer manuellement une transaction"
|
|
1447
|
+
},
|
|
1448
|
+
args: {
|
|
1449
|
+
id: {
|
|
1450
|
+
type: "string",
|
|
1451
|
+
description: "ID de la transaction (requis)",
|
|
1452
|
+
required: true
|
|
1453
|
+
},
|
|
1454
|
+
"label-id": {
|
|
1455
|
+
type: "string",
|
|
1456
|
+
description: "ID du label \xE0 assigner (requis)",
|
|
1457
|
+
required: true
|
|
1458
|
+
},
|
|
1459
|
+
"label-name": {
|
|
1460
|
+
type: "string",
|
|
1461
|
+
description: "Nom du label (optionnel, pour affichage)"
|
|
1462
|
+
},
|
|
1463
|
+
"dry-run": {
|
|
1464
|
+
type: "boolean",
|
|
1465
|
+
description: "Pr\xE9visualiser sans appliquer",
|
|
1466
|
+
default: false
|
|
1467
|
+
},
|
|
1468
|
+
...formatArg
|
|
1469
|
+
},
|
|
1470
|
+
async run({ args }) {
|
|
1471
|
+
try {
|
|
1472
|
+
const client = new TiimeClient({ companyId: getCompanyId() });
|
|
1473
|
+
const transactionId = Number(args.id);
|
|
1474
|
+
const labelId = Number(args["label-id"]);
|
|
1475
|
+
const [transaction, suggestions] = await Promise.all([
|
|
1476
|
+
client.bankTransactions.get(transactionId),
|
|
1477
|
+
client.bankTransactions.labelSuggestions(transactionId)
|
|
1478
|
+
]);
|
|
1479
|
+
let matchedLabel = suggestions.find(
|
|
1480
|
+
(s) => s.id === labelId
|
|
1481
|
+
);
|
|
1482
|
+
if (!matchedLabel) {
|
|
1483
|
+
const [labels, standardLabels] = await Promise.all([
|
|
1484
|
+
client.labels.list(),
|
|
1485
|
+
client.labels.standard()
|
|
1486
|
+
]);
|
|
1487
|
+
const allLabels = [...labels, ...standardLabels];
|
|
1488
|
+
const found = allLabels.find((l) => l.id === labelId);
|
|
1489
|
+
if (found) {
|
|
1490
|
+
matchedLabel = {
|
|
1491
|
+
id: found.id,
|
|
1492
|
+
label: found.name,
|
|
1493
|
+
name: found.name,
|
|
1494
|
+
acronym: "",
|
|
1495
|
+
color: found.color,
|
|
1496
|
+
client: null
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
if (!matchedLabel) {
|
|
1501
|
+
outputError(
|
|
1502
|
+
new Error(
|
|
1503
|
+
`Label #${labelId} introuvable dans les suggestions ni dans les labels disponibles`
|
|
1504
|
+
)
|
|
1505
|
+
);
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
const imputationLabel = {
|
|
1509
|
+
...matchedLabel,
|
|
1510
|
+
disabled: false
|
|
1511
|
+
};
|
|
1512
|
+
const imputationParams = [
|
|
1513
|
+
{
|
|
1514
|
+
label: imputationLabel,
|
|
1515
|
+
amount: transaction.amount,
|
|
1516
|
+
documents: [],
|
|
1517
|
+
accountant_detail_requests: []
|
|
1518
|
+
}
|
|
1519
|
+
];
|
|
1520
|
+
const displayName = args["label-name"] ?? matchedLabel.name ?? matchedLabel.label;
|
|
1521
|
+
if (args["dry-run"]) {
|
|
1522
|
+
output(
|
|
1523
|
+
{
|
|
1524
|
+
dry_run: true,
|
|
1525
|
+
transaction_id: transactionId,
|
|
1526
|
+
wording: transaction.wording,
|
|
1527
|
+
amount: transaction.amount,
|
|
1528
|
+
currency: transaction.currency,
|
|
1529
|
+
label_id: labelId,
|
|
1530
|
+
label_name: displayName
|
|
1531
|
+
},
|
|
1532
|
+
{ format: args.format }
|
|
1533
|
+
);
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
const result = await client.bankTransactions.impute(
|
|
1537
|
+
transactionId,
|
|
1538
|
+
imputationParams
|
|
1539
|
+
);
|
|
1540
|
+
output(result, { format: args.format });
|
|
1541
|
+
} catch (e) {
|
|
1542
|
+
outputError(e);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}),
|
|
1546
|
+
"auto-impute": defineCommand3({
|
|
1547
|
+
meta: {
|
|
1548
|
+
name: "auto-impute",
|
|
1549
|
+
description: "Auto-imputer les transactions non imput\xE9es via les suggestions"
|
|
1550
|
+
},
|
|
1551
|
+
args: {
|
|
1552
|
+
"dry-run": {
|
|
1553
|
+
type: "boolean",
|
|
1554
|
+
description: "Mode pr\xE9visualisation (par d\xE9faut)",
|
|
1555
|
+
default: true
|
|
1556
|
+
},
|
|
1557
|
+
apply: {
|
|
1558
|
+
type: "boolean",
|
|
1559
|
+
description: "Appliquer les imputations (d\xE9sactive dry-run)",
|
|
1560
|
+
default: false
|
|
1561
|
+
},
|
|
1562
|
+
"all-companies": {
|
|
1563
|
+
type: "boolean",
|
|
1564
|
+
description: "Traiter toutes les entreprises du compte (sinon entreprise active)",
|
|
1565
|
+
default: false
|
|
1566
|
+
},
|
|
1567
|
+
company: {
|
|
1568
|
+
type: "string",
|
|
1569
|
+
description: "ID ou nom de l'entreprise cible (peut \xEAtre r\xE9p\xE9t\xE9 avec virgule : 50824,117954)"
|
|
1570
|
+
},
|
|
1571
|
+
...formatArg
|
|
1572
|
+
},
|
|
1573
|
+
async run({ args }) {
|
|
1574
|
+
try {
|
|
1575
|
+
let companyIds;
|
|
1576
|
+
if (args["all-companies"]) {
|
|
1577
|
+
const rootClient = new TiimeClient({ companyId: 0 });
|
|
1578
|
+
const companies = await rootClient.listCompanies();
|
|
1579
|
+
companyIds = companies.map((c) => c.id);
|
|
1580
|
+
} else if (args.company) {
|
|
1581
|
+
const parts = args.company.split(",").map((s) => s.trim());
|
|
1582
|
+
const allNumeric = parts.every((p2) => /^\d+$/.test(p2));
|
|
1583
|
+
if (allNumeric) {
|
|
1584
|
+
companyIds = parts.map(Number);
|
|
1585
|
+
} else {
|
|
1586
|
+
const rootClient = new TiimeClient({ companyId: 0 });
|
|
1587
|
+
const companies = await rootClient.listCompanies();
|
|
1588
|
+
companyIds = resolveCompanyIds(parts, companies);
|
|
1589
|
+
}
|
|
1590
|
+
} else {
|
|
1591
|
+
companyIds = [getCompanyId()];
|
|
1592
|
+
}
|
|
1593
|
+
const allProposals = [];
|
|
1594
|
+
for (const companyId of companyIds) {
|
|
1595
|
+
const client = new TiimeClient({ companyId });
|
|
1596
|
+
let companyName = String(companyId);
|
|
1597
|
+
try {
|
|
1598
|
+
const info = await client.company.get();
|
|
1599
|
+
companyName = info.name ?? String(companyId);
|
|
1600
|
+
} catch {
|
|
1601
|
+
}
|
|
1602
|
+
const proposals = await autoImputeForCompany(
|
|
1603
|
+
client,
|
|
1604
|
+
companyId,
|
|
1605
|
+
companyName,
|
|
1606
|
+
{ apply: args.apply }
|
|
1607
|
+
);
|
|
1608
|
+
allProposals.push(...proposals);
|
|
1609
|
+
}
|
|
1610
|
+
output(allProposals, { format: args.format });
|
|
1611
|
+
} catch (e) {
|
|
1612
|
+
outputError(e);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1092
1615
|
})
|
|
1093
1616
|
}
|
|
1094
1617
|
});
|
|
1095
1618
|
|
|
1096
1619
|
// src/cli/commands/clients.ts
|
|
1097
|
-
import { defineCommand as
|
|
1098
|
-
var clientsCommand =
|
|
1620
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
1621
|
+
var clientsCommand = defineCommand4({
|
|
1099
1622
|
meta: { name: "clients", description: "Gestion des clients" },
|
|
1100
1623
|
subCommands: {
|
|
1101
|
-
list:
|
|
1624
|
+
list: defineCommand4({
|
|
1102
1625
|
meta: { name: "list", description: "Lister les clients" },
|
|
1103
1626
|
args: {
|
|
1104
1627
|
...formatArg,
|
|
@@ -1120,7 +1643,7 @@ var clientsCommand = defineCommand3({
|
|
|
1120
1643
|
}
|
|
1121
1644
|
}
|
|
1122
1645
|
}),
|
|
1123
|
-
get:
|
|
1646
|
+
get: defineCommand4({
|
|
1124
1647
|
meta: { name: "get", description: "D\xE9tails d'un client" },
|
|
1125
1648
|
args: {
|
|
1126
1649
|
id: { type: "string", description: "ID du client", required: true }
|
|
@@ -1135,7 +1658,7 @@ var clientsCommand = defineCommand3({
|
|
|
1135
1658
|
}
|
|
1136
1659
|
}
|
|
1137
1660
|
}),
|
|
1138
|
-
create:
|
|
1661
|
+
create: defineCommand4({
|
|
1139
1662
|
meta: { name: "create", description: "Cr\xE9er un client" },
|
|
1140
1663
|
args: {
|
|
1141
1664
|
name: {
|
|
@@ -1192,7 +1715,7 @@ var clientsCommand = defineCommand3({
|
|
|
1192
1715
|
}
|
|
1193
1716
|
}
|
|
1194
1717
|
}),
|
|
1195
|
-
search:
|
|
1718
|
+
search: defineCommand4({
|
|
1196
1719
|
meta: { name: "search", description: "Rechercher un client" },
|
|
1197
1720
|
args: {
|
|
1198
1721
|
...formatArg,
|
|
@@ -1216,11 +1739,11 @@ var clientsCommand = defineCommand3({
|
|
|
1216
1739
|
});
|
|
1217
1740
|
|
|
1218
1741
|
// src/cli/commands/company.ts
|
|
1219
|
-
import { defineCommand as
|
|
1220
|
-
var companyCommand =
|
|
1742
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
1743
|
+
var companyCommand = defineCommand5({
|
|
1221
1744
|
meta: { name: "company", description: "Gestion de l'entreprise" },
|
|
1222
1745
|
subCommands: {
|
|
1223
|
-
list:
|
|
1746
|
+
list: defineCommand5({
|
|
1224
1747
|
meta: { name: "list", description: "Lister toutes les entreprises" },
|
|
1225
1748
|
args: { ...formatArg },
|
|
1226
1749
|
async run({ args }) {
|
|
@@ -1242,7 +1765,7 @@ var companyCommand = defineCommand4({
|
|
|
1242
1765
|
}
|
|
1243
1766
|
}
|
|
1244
1767
|
}),
|
|
1245
|
-
get:
|
|
1768
|
+
get: defineCommand5({
|
|
1246
1769
|
meta: { name: "get", description: "D\xE9tails de l'entreprise active" },
|
|
1247
1770
|
async run() {
|
|
1248
1771
|
try {
|
|
@@ -1256,7 +1779,7 @@ var companyCommand = defineCommand4({
|
|
|
1256
1779
|
}
|
|
1257
1780
|
}
|
|
1258
1781
|
}),
|
|
1259
|
-
use:
|
|
1782
|
+
use: defineCommand5({
|
|
1260
1783
|
meta: { name: "use", description: "D\xE9finir l'entreprise active" },
|
|
1261
1784
|
args: {
|
|
1262
1785
|
id: {
|
|
@@ -1272,7 +1795,7 @@ var companyCommand = defineCommand4({
|
|
|
1272
1795
|
output({ status: "ok", companyId: config.companyId });
|
|
1273
1796
|
}
|
|
1274
1797
|
}),
|
|
1275
|
-
me:
|
|
1798
|
+
me: defineCommand5({
|
|
1276
1799
|
meta: {
|
|
1277
1800
|
name: "me",
|
|
1278
1801
|
description: "Info utilisateur courant (inclut active_company)"
|
|
@@ -1291,7 +1814,7 @@ var companyCommand = defineCommand4({
|
|
|
1291
1814
|
});
|
|
1292
1815
|
|
|
1293
1816
|
// src/cli/commands/completion.ts
|
|
1294
|
-
import { defineCommand as
|
|
1817
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
1295
1818
|
var commands = {
|
|
1296
1819
|
auth: {
|
|
1297
1820
|
description: "Gestion de l'authentification",
|
|
@@ -1516,7 +2039,7 @@ var generateFish = () => {
|
|
|
1516
2039
|
return `${lines.join("\n")}
|
|
1517
2040
|
`;
|
|
1518
2041
|
};
|
|
1519
|
-
var completionCommand =
|
|
2042
|
+
var completionCommand = defineCommand6({
|
|
1520
2043
|
meta: {
|
|
1521
2044
|
name: "completion",
|
|
1522
2045
|
description: "G\xE9n\xE9rer le script d'autocompl\xE9tion shell"
|
|
@@ -1553,11 +2076,11 @@ var completionCommand = defineCommand5({
|
|
|
1553
2076
|
// src/cli/commands/documents.ts
|
|
1554
2077
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
1555
2078
|
import { basename } from "path";
|
|
1556
|
-
import { defineCommand as
|
|
1557
|
-
var documentsCommand =
|
|
2079
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
2080
|
+
var documentsCommand = defineCommand7({
|
|
1558
2081
|
meta: { name: "documents", description: "Gestion des documents" },
|
|
1559
2082
|
subCommands: {
|
|
1560
|
-
list:
|
|
2083
|
+
list: defineCommand7({
|
|
1561
2084
|
meta: { name: "list", description: "Lister les documents" },
|
|
1562
2085
|
args: {
|
|
1563
2086
|
...formatArg,
|
|
@@ -1585,7 +2108,7 @@ var documentsCommand = defineCommand6({
|
|
|
1585
2108
|
}
|
|
1586
2109
|
}
|
|
1587
2110
|
}),
|
|
1588
|
-
upload:
|
|
2111
|
+
upload: defineCommand7({
|
|
1589
2112
|
meta: { name: "upload", description: "Uploader un justificatif" },
|
|
1590
2113
|
args: {
|
|
1591
2114
|
file: {
|
|
@@ -1614,7 +2137,7 @@ var documentsCommand = defineCommand6({
|
|
|
1614
2137
|
}
|
|
1615
2138
|
}
|
|
1616
2139
|
}),
|
|
1617
|
-
download:
|
|
2140
|
+
download: defineCommand7({
|
|
1618
2141
|
meta: { name: "download", description: "T\xE9l\xE9charger un document" },
|
|
1619
2142
|
args: {
|
|
1620
2143
|
id: {
|
|
@@ -1640,7 +2163,7 @@ var documentsCommand = defineCommand6({
|
|
|
1640
2163
|
}
|
|
1641
2164
|
}
|
|
1642
2165
|
}),
|
|
1643
|
-
categories:
|
|
2166
|
+
categories: defineCommand7({
|
|
1644
2167
|
meta: {
|
|
1645
2168
|
name: "categories",
|
|
1646
2169
|
description: "Lister les cat\xE9gories de documents"
|
|
@@ -1660,11 +2183,11 @@ var documentsCommand = defineCommand6({
|
|
|
1660
2183
|
});
|
|
1661
2184
|
|
|
1662
2185
|
// src/cli/commands/expenses.ts
|
|
1663
|
-
import { defineCommand as
|
|
1664
|
-
var expensesCommand =
|
|
2186
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
2187
|
+
var expensesCommand = defineCommand8({
|
|
1665
2188
|
meta: { name: "expenses", description: "Gestion des notes de frais" },
|
|
1666
2189
|
subCommands: {
|
|
1667
|
-
list:
|
|
2190
|
+
list: defineCommand8({
|
|
1668
2191
|
meta: { name: "list", description: "Lister les notes de frais" },
|
|
1669
2192
|
args: {
|
|
1670
2193
|
...formatArg,
|
|
@@ -1684,7 +2207,7 @@ var expensesCommand = defineCommand7({
|
|
|
1684
2207
|
}
|
|
1685
2208
|
}
|
|
1686
2209
|
}),
|
|
1687
|
-
get:
|
|
2210
|
+
get: defineCommand8({
|
|
1688
2211
|
meta: { name: "get", description: "D\xE9tails d'une note de frais" },
|
|
1689
2212
|
args: {
|
|
1690
2213
|
id: {
|
|
@@ -1703,7 +2226,7 @@ var expensesCommand = defineCommand7({
|
|
|
1703
2226
|
}
|
|
1704
2227
|
}
|
|
1705
2228
|
}),
|
|
1706
|
-
create:
|
|
2229
|
+
create: defineCommand8({
|
|
1707
2230
|
meta: { name: "create", description: "Cr\xE9er une note de frais" },
|
|
1708
2231
|
args: {
|
|
1709
2232
|
name: {
|
|
@@ -1734,11 +2257,11 @@ var expensesCommand = defineCommand7({
|
|
|
1734
2257
|
|
|
1735
2258
|
// src/cli/commands/invoices.ts
|
|
1736
2259
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
1737
|
-
import { defineCommand as
|
|
1738
|
-
var invoicesCommand =
|
|
2260
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
2261
|
+
var invoicesCommand = defineCommand9({
|
|
1739
2262
|
meta: { name: "invoices", description: "Gestion des factures" },
|
|
1740
2263
|
subCommands: {
|
|
1741
|
-
list:
|
|
2264
|
+
list: defineCommand9({
|
|
1742
2265
|
meta: { name: "list", description: "Lister les factures" },
|
|
1743
2266
|
args: {
|
|
1744
2267
|
...formatArg,
|
|
@@ -1787,7 +2310,7 @@ var invoicesCommand = defineCommand8({
|
|
|
1787
2310
|
}
|
|
1788
2311
|
}
|
|
1789
2312
|
}),
|
|
1790
|
-
get:
|
|
2313
|
+
get: defineCommand9({
|
|
1791
2314
|
meta: { name: "get", description: "D\xE9tails d'une facture" },
|
|
1792
2315
|
args: {
|
|
1793
2316
|
id: { type: "string", description: "ID de la facture", required: true }
|
|
@@ -1802,7 +2325,7 @@ var invoicesCommand = defineCommand8({
|
|
|
1802
2325
|
}
|
|
1803
2326
|
}
|
|
1804
2327
|
}),
|
|
1805
|
-
create:
|
|
2328
|
+
create: defineCommand9({
|
|
1806
2329
|
meta: {
|
|
1807
2330
|
name: "create",
|
|
1808
2331
|
description: "Cr\xE9er une facture (brouillon par d\xE9faut)"
|
|
@@ -1931,7 +2454,7 @@ var invoicesCommand = defineCommand8({
|
|
|
1931
2454
|
}
|
|
1932
2455
|
}
|
|
1933
2456
|
}),
|
|
1934
|
-
duplicate:
|
|
2457
|
+
duplicate: defineCommand9({
|
|
1935
2458
|
meta: {
|
|
1936
2459
|
name: "duplicate",
|
|
1937
2460
|
description: "Dupliquer une facture existante en brouillon"
|
|
@@ -1964,7 +2487,7 @@ var invoicesCommand = defineCommand8({
|
|
|
1964
2487
|
}
|
|
1965
2488
|
}
|
|
1966
2489
|
}),
|
|
1967
|
-
update:
|
|
2490
|
+
update: defineCommand9({
|
|
1968
2491
|
meta: { name: "update", description: "Mettre \xE0 jour une facture" },
|
|
1969
2492
|
args: {
|
|
1970
2493
|
id: {
|
|
@@ -2010,7 +2533,7 @@ var invoicesCommand = defineCommand8({
|
|
|
2010
2533
|
}
|
|
2011
2534
|
}
|
|
2012
2535
|
}),
|
|
2013
|
-
send:
|
|
2536
|
+
send: defineCommand9({
|
|
2014
2537
|
meta: { name: "send", description: "Envoyer une facture par email" },
|
|
2015
2538
|
args: {
|
|
2016
2539
|
id: {
|
|
@@ -2050,7 +2573,7 @@ var invoicesCommand = defineCommand8({
|
|
|
2050
2573
|
}
|
|
2051
2574
|
}
|
|
2052
2575
|
}),
|
|
2053
|
-
pdf:
|
|
2576
|
+
pdf: defineCommand9({
|
|
2054
2577
|
meta: {
|
|
2055
2578
|
name: "pdf",
|
|
2056
2579
|
description: "T\xE9l\xE9charger le PDF d'une facture"
|
|
@@ -2078,7 +2601,7 @@ var invoicesCommand = defineCommand8({
|
|
|
2078
2601
|
}
|
|
2079
2602
|
}
|
|
2080
2603
|
}),
|
|
2081
|
-
delete:
|
|
2604
|
+
delete: defineCommand9({
|
|
2082
2605
|
meta: { name: "delete", description: "Supprimer une facture brouillon" },
|
|
2083
2606
|
args: {
|
|
2084
2607
|
id: {
|
|
@@ -2101,11 +2624,11 @@ var invoicesCommand = defineCommand8({
|
|
|
2101
2624
|
});
|
|
2102
2625
|
|
|
2103
2626
|
// src/cli/commands/labels.ts
|
|
2104
|
-
import { defineCommand as
|
|
2105
|
-
var labelsCommand =
|
|
2627
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
2628
|
+
var labelsCommand = defineCommand10({
|
|
2106
2629
|
meta: { name: "labels", description: "Gestion des labels et tags" },
|
|
2107
2630
|
subCommands: {
|
|
2108
|
-
list:
|
|
2631
|
+
list: defineCommand10({
|
|
2109
2632
|
meta: { name: "list", description: "Lister les labels personnalis\xE9s" },
|
|
2110
2633
|
args: { ...formatArg },
|
|
2111
2634
|
async run({ args }) {
|
|
@@ -2118,7 +2641,7 @@ var labelsCommand = defineCommand9({
|
|
|
2118
2641
|
}
|
|
2119
2642
|
}
|
|
2120
2643
|
}),
|
|
2121
|
-
standard:
|
|
2644
|
+
standard: defineCommand10({
|
|
2122
2645
|
meta: { name: "standard", description: "Lister les labels standards" },
|
|
2123
2646
|
args: { ...formatArg },
|
|
2124
2647
|
async run({ args }) {
|
|
@@ -2131,7 +2654,7 @@ var labelsCommand = defineCommand9({
|
|
|
2131
2654
|
}
|
|
2132
2655
|
}
|
|
2133
2656
|
}),
|
|
2134
|
-
tags:
|
|
2657
|
+
tags: defineCommand10({
|
|
2135
2658
|
meta: { name: "tags", description: "Lister les tags" },
|
|
2136
2659
|
args: { ...formatArg },
|
|
2137
2660
|
async run({ args }) {
|
|
@@ -2149,7 +2672,7 @@ var labelsCommand = defineCommand9({
|
|
|
2149
2672
|
|
|
2150
2673
|
// src/cli/commands/open.ts
|
|
2151
2674
|
import { exec } from "child_process";
|
|
2152
|
-
import { defineCommand as
|
|
2675
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
2153
2676
|
var APP_BASE_URL = "https://apps.tiime.fr";
|
|
2154
2677
|
var sections = {
|
|
2155
2678
|
invoices: "/invoicing/invoices",
|
|
@@ -2172,7 +2695,7 @@ var buildUrl = (section) => {
|
|
|
2172
2695
|
const companyId = getCompanyId();
|
|
2173
2696
|
return `${APP_BASE_URL}/companies/${companyId}${path}`;
|
|
2174
2697
|
};
|
|
2175
|
-
var openCommand =
|
|
2698
|
+
var openCommand = defineCommand11({
|
|
2176
2699
|
meta: {
|
|
2177
2700
|
name: "open",
|
|
2178
2701
|
description: "Ouvrir Tiime dans le navigateur"
|
|
@@ -2197,11 +2720,11 @@ var openCommand = defineCommand10({
|
|
|
2197
2720
|
|
|
2198
2721
|
// src/cli/commands/quotations.ts
|
|
2199
2722
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
2200
|
-
import { defineCommand as
|
|
2201
|
-
var quotationsCommand =
|
|
2723
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
2724
|
+
var quotationsCommand = defineCommand12({
|
|
2202
2725
|
meta: { name: "quotations", description: "Gestion des devis" },
|
|
2203
2726
|
subCommands: {
|
|
2204
|
-
list:
|
|
2727
|
+
list: defineCommand12({
|
|
2205
2728
|
meta: { name: "list", description: "Lister les devis" },
|
|
2206
2729
|
args: { ...formatArg },
|
|
2207
2730
|
async run({ args }) {
|
|
@@ -2214,7 +2737,7 @@ var quotationsCommand = defineCommand11({
|
|
|
2214
2737
|
}
|
|
2215
2738
|
}
|
|
2216
2739
|
}),
|
|
2217
|
-
get:
|
|
2740
|
+
get: defineCommand12({
|
|
2218
2741
|
meta: { name: "get", description: "D\xE9tails d'un devis" },
|
|
2219
2742
|
args: {
|
|
2220
2743
|
id: { type: "string", description: "ID du devis", required: true }
|
|
@@ -2229,7 +2752,7 @@ var quotationsCommand = defineCommand11({
|
|
|
2229
2752
|
}
|
|
2230
2753
|
}
|
|
2231
2754
|
}),
|
|
2232
|
-
create:
|
|
2755
|
+
create: defineCommand12({
|
|
2233
2756
|
meta: {
|
|
2234
2757
|
name: "create",
|
|
2235
2758
|
description: "Cr\xE9er un devis (brouillon par d\xE9faut)"
|
|
@@ -2305,7 +2828,7 @@ var quotationsCommand = defineCommand11({
|
|
|
2305
2828
|
}
|
|
2306
2829
|
}
|
|
2307
2830
|
}),
|
|
2308
|
-
pdf:
|
|
2831
|
+
pdf: defineCommand12({
|
|
2309
2832
|
meta: {
|
|
2310
2833
|
name: "pdf",
|
|
2311
2834
|
description: "T\xE9l\xE9charger le PDF d'un devis"
|
|
@@ -2333,7 +2856,7 @@ var quotationsCommand = defineCommand11({
|
|
|
2333
2856
|
}
|
|
2334
2857
|
}
|
|
2335
2858
|
}),
|
|
2336
|
-
send:
|
|
2859
|
+
send: defineCommand12({
|
|
2337
2860
|
meta: { name: "send", description: "Envoyer un devis par email" },
|
|
2338
2861
|
args: {
|
|
2339
2862
|
id: {
|
|
@@ -2377,8 +2900,8 @@ var quotationsCommand = defineCommand11({
|
|
|
2377
2900
|
});
|
|
2378
2901
|
|
|
2379
2902
|
// src/cli/commands/status.ts
|
|
2380
|
-
import { defineCommand as
|
|
2381
|
-
var statusCommand =
|
|
2903
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
2904
|
+
var statusCommand = defineCommand13({
|
|
2382
2905
|
meta: { name: "status", description: "R\xE9sum\xE9 rapide de la situation" },
|
|
2383
2906
|
args: { ...formatArg },
|
|
2384
2907
|
async run({ args }) {
|
|
@@ -2429,11 +2952,11 @@ var statusCommand = defineCommand12({
|
|
|
2429
2952
|
});
|
|
2430
2953
|
|
|
2431
2954
|
// src/cli/commands/version.ts
|
|
2432
|
-
import { defineCommand as
|
|
2433
|
-
var versionCommand =
|
|
2955
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
2956
|
+
var versionCommand = defineCommand14({
|
|
2434
2957
|
meta: { name: "version", description: "Afficher la version" },
|
|
2435
2958
|
run() {
|
|
2436
|
-
output({ version: "1.
|
|
2959
|
+
output({ version: "1.2.0", node: process.version });
|
|
2437
2960
|
}
|
|
2438
2961
|
});
|
|
2439
2962
|
|
|
@@ -2451,6 +2974,7 @@ var descriptionTranslations = {
|
|
|
2451
2974
|
"Gestion des notes de frais": "Expense report management",
|
|
2452
2975
|
"Gestion des documents": "Document management",
|
|
2453
2976
|
"Gestion des labels et tags": "Label and tag management",
|
|
2977
|
+
"Audit comptable multi-entreprises": "Multi-company accounting audit",
|
|
2454
2978
|
"R\xE9sum\xE9 rapide de la situation": "Quick status summary",
|
|
2455
2979
|
"Ouvrir Tiime dans le navigateur": "Open Tiime in browser",
|
|
2456
2980
|
"Afficher la version": "Show version",
|
|
@@ -2562,7 +3086,10 @@ var descriptionTranslations = {
|
|
|
2562
3086
|
"Section \xE0 ouvrir (invoices, quotations, clients, bank, documents, expenses)": "Section to open (invoices, quotations, clients, bank, documents, expenses)",
|
|
2563
3087
|
"Nom de la note de frais": "Expense report name",
|
|
2564
3088
|
"Date (YYYY-MM-DD)": "Date (YYYY-MM-DD)",
|
|
2565
|
-
"Titre du devis": "Quotation title"
|
|
3089
|
+
"Titre du devis": "Quotation title",
|
|
3090
|
+
"Traiter toutes les entreprises": "Process all companies",
|
|
3091
|
+
"Entreprise(s) cible(s) (ID ou nom, s\xE9par\xE9s par des virgules)": "Target company(ies) (ID or name, comma-separated)",
|
|
3092
|
+
"Appliquer les corrections automatiques (imputation auto)": "Apply automatic fixes (auto-imputation)"
|
|
2566
3093
|
};
|
|
2567
3094
|
var frameworkTranslations = {
|
|
2568
3095
|
fr: {
|
|
@@ -2609,13 +3136,14 @@ var translateHelp = (text2) => {
|
|
|
2609
3136
|
};
|
|
2610
3137
|
|
|
2611
3138
|
// src/cli/index.ts
|
|
2612
|
-
var main =
|
|
3139
|
+
var main = defineCommand15({
|
|
2613
3140
|
meta: {
|
|
2614
3141
|
name: "tiime",
|
|
2615
3142
|
version: "1.0.0",
|
|
2616
3143
|
description: "CLI pour la comptabilit\xE9 Tiime \u2014 sortie JSON pour agents IA"
|
|
2617
3144
|
},
|
|
2618
3145
|
subCommands: {
|
|
3146
|
+
audit: auditCommand,
|
|
2619
3147
|
auth: authCommand,
|
|
2620
3148
|
company: companyCommand,
|
|
2621
3149
|
invoices: invoicesCommand,
|