@profullstack/coinpay 0.23.0 → 0.24.1

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/bin/coinpay.js CHANGED
@@ -710,6 +710,9 @@ ${colors.cyan}Commands:${colors.reset}
710
710
  books summary Totals by tax category (--period 2026|2026-Q3|2026-08, --scope)
711
711
  books export CPA pack (--period, --scope, --format csv|pdf|html|json, --output;
712
712
  --with-documents: a ZIP with the period's tax documents, up to 8 MiB)
713
+ pnl Profit and loss, personal and business as separate files
714
+ (--scope personal|business, --months 3 (default: last 3
715
+ complete months) or --from/--to, --name "Holder", --format pdf|html|csv|json)
713
716
  payloads [list|download <id>] Raw provider responses, exactly as received
714
717
  reports send <id> Email a report (--to a@x,b@y, --format pdf,csv, --message, --no-attach)
715
718
  books send Email the CPA pack (--to, --period, --scope, --format,
@@ -5241,6 +5244,8 @@ async function handleFinances(subcommand, args, flags) {
5241
5244
  case 'reports':
5242
5245
  case 'statements':
5243
5246
  case 'books':
5247
+ case 'pnl':
5248
+ case 'profit-loss':
5244
5249
  case 'payloads':
5245
5250
  case 'digest':
5246
5251
  case 'due':
@@ -5261,7 +5266,7 @@ async function handleFinances(subcommand, args, flags) {
5261
5266
 
5262
5267
  default:
5263
5268
  print.error(`Unknown finances command: ${subcommand}`);
5264
- console.log('Usage: coinpay finances [tui|summary|accounts|ledger|connections|sync|connect|disconnect|backfill|jobs|coverage|report|reports|statements|books|payloads|digest|due|recurring|due-day|daily]');
5269
+ console.log('Usage: coinpay finances [tui|summary|accounts|ledger|connections|sync|connect|disconnect|backfill|jobs|coverage|report|reports|statements|books|pnl|payloads|digest|due|recurring|due-day|daily]');
5265
5270
  process.exit(1);
5266
5271
  }
5267
5272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/coinpay",
3
- "version": "0.23.0",
3
+ "version": "0.24.1",
4
4
  "description": "CoinPay SDK & CLI \u2014 Accept cryptocurrency and card payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet, swap and a live finances dashboard",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -802,6 +802,30 @@ export async function runFinancesCommand(subcommand, args, flags, ctx) {
802
802
  throw new CliExit(EXIT.INVALID, 'Usage: coinpay finances books [queue|confirm <id>|confirm-all --yes|categorize|rules [add|delete]|summary|export|send]');
803
803
  }
804
804
 
805
+ case 'pnl':
806
+ case 'profit-loss': {
807
+ const scopes = listFlag(flags.scope);
808
+ const wanted = scopes.length ? scopes : ['personal', 'business'];
809
+ for (const s of wanted) if (s !== 'personal' && s !== 'business') throw new CliExit(EXIT.INVALID, `--scope must be personal, business or both (got ${s})`);
810
+ const format = typeof flags.format === 'string' ? flags.format.toLowerCase() : 'pdf';
811
+ if (!['pdf', 'html', 'csv', 'json'].includes(format)) throw new CliExit(EXIT.INVALID, '--format must be pdf, html, csv or json');
812
+ const months = flags.months === undefined ? undefined : Number(flags.months);
813
+ if (months !== undefined && (!Number.isInteger(months) || months < 1 || months > 24)) throw new CliExit(EXIT.INVALID, '--months must be 1 to 24');
814
+ const period = typeof flags.period === 'string' ? flags.period : undefined;
815
+ const from = typeof flags.from === 'string' ? flags.from : undefined;
816
+ const to = typeof flags.to === 'string' ? flags.to : undefined;
817
+ const timezone = typeof flags.timezone === 'string' ? flags.timezone : undefined;
818
+ const name = typeof flags.name === 'string' ? flags.name : undefined;
819
+ const written = [];
820
+ for (const scope of wanted) {
821
+ const file = await api.exportPnl(client, { scope, months, period, from, to, timezone, name, format });
822
+ const output = typeof flags.output === 'string' && wanted.length === 1 ? flags.output : file.filename || `pnl-${scope}.${format}`;
823
+ written.push({ scope, output: writeDownload(output, Buffer.from(file.bytes), { overwrite: flags.overwrite === true }), bytes: file.bytes.length });
824
+ }
825
+ emit({ files: written }, written.map((w) => `Wrote ${w.output} (${w.scope}, ${w.bytes} bytes)`).join('\n'));
826
+ return EXIT.OK;
827
+ }
828
+
805
829
  case 'digest': {
806
830
  const action = args[0] || 'show';
807
831
  const DAY_NAMES = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
@@ -966,4 +990,4 @@ export async function runFinancesCommand(subcommand, args, flags, ctx) {
966
990
  }
967
991
  }
968
992
 
969
- export const EXTENDED_SUBCOMMANDS = ['connect', 'disconnect', 'consent', 'backfill', 'jobs', 'coverage', 'report', 'reports', 'statements', 'books', 'payloads', 'digest', 'due', 'due-soon', 'recurring', 'due-day', 'daily'];
993
+ export const EXTENDED_SUBCOMMANDS = ['connect', 'disconnect', 'consent', 'backfill', 'jobs', 'coverage', 'report', 'reports', 'statements', 'books', 'pnl', 'profit-loss', 'payloads', 'digest', 'due', 'due-soon', 'recurring', 'due-day', 'daily'];
@@ -397,6 +397,16 @@ export async function exportBooks(client, { period, from, to, timezone, scope, f
397
397
  return client.requestBinary(`/finances/books/export${query({ period, from, to, timezone, scope, format, with_documents: withDocuments ? 1 : undefined })}`);
398
398
  }
399
399
 
400
+ // ── Profit and loss ──
401
+
402
+ /**
403
+ * Profit and loss statement for one scope. With no period it covers the
404
+ * last `months` complete calendar months (server default 3).
405
+ */
406
+ export async function exportPnl(client, { scope, months, period, from, to, timezone, name, format = 'pdf' } = {}) {
407
+ return client.requestBinary(`/finances/pnl${query({ scope, months, period, from, to, timezone, name, format })}`);
408
+ }
409
+
400
410
  // ── Raw provider payloads ──
401
411
 
402
412
  export async function listFinancePayloads(client, { connectionId, limit, offset } = {}) {