@targlobal/mission-control 1.5.7 → 1.5.8

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/dist/index.js CHANGED
@@ -503,7 +503,7 @@ const showDashboard = async () => {
503
503
  console.log(chalk_1.default.cyan('┌─────────────────────────────┐'));
504
504
  console.log(chalk_1.default.cyan('│') + ` ${chalk_1.default.bgCyan.black('TASKS')} ${chalk_1.default.bold.white(String(stats.my_tasks).padStart(3))} ${chalk_1.default.bgRed.white('CRIT')} ${chalk_1.default.bold.red(String(stats.critical_count).padStart(2))} ${chalk_1.default.bgYellow.black('OVR')} ${chalk_1.default.bold.yellow(String(stats.overdue_tasks).padStart(2))} ` + chalk_1.default.cyan('│'));
505
505
  console.log(chalk_1.default.cyan('├─────────────────────────────┤'));
506
- console.log(chalk_1.default.cyan('│') + ` ${chalk_1.default.cyan('[1]')}Tasks ${chalk_1.default.cyan('[2]')}New ${chalk_1.default.cyan('[3]')}Pay ${chalk_1.default.cyan('[4]')}Urg ${chalk_1.default.cyan('[5]')}Q ` + chalk_1.default.cyan('│'));
506
+ console.log(chalk_1.default.cyan('│') + ` ${chalk_1.default.cyan('[1]')}Tasks ${chalk_1.default.cyan('[2]')}New ${chalk_1.default.cyan('[3]')}Pay ${chalk_1.default.cyan('[4]')}Urg ${chalk_1.default.cyan('[5]')}Smart ` + chalk_1.default.cyan('│'));
507
507
  console.log(chalk_1.default.cyan('└─────────────────────────────┘'));
508
508
  console.log('');
509
509
  // Show urgent count only in compact mode
@@ -525,7 +525,7 @@ const showDashboard = async () => {
525
525
  console.log(chalk_1.default.cyan('║') + ' ' + chalk_1.default.cyan('║'));
526
526
  console.log(chalk_1.default.cyan('╠══════════════════════════════════════════════════════════════════════╣'));
527
527
  console.log(chalk_1.default.cyan('║') + chalk_1.default.dim(' Quick Actions: ') + chalk_1.default.cyan('║'));
528
- console.log(chalk_1.default.cyan('║') + ` ${chalk_1.default.cyan('[1]')} My Tasks ${chalk_1.default.cyan('[2]')} New Task ${chalk_1.default.cyan('[3]')} Payouts ${chalk_1.default.cyan('[4]')} Urgent ${chalk_1.default.cyan('[5]')} Queue ` + chalk_1.default.cyan('║'));
528
+ console.log(chalk_1.default.cyan('║') + ` ${chalk_1.default.cyan('[1]')} My Tasks ${chalk_1.default.cyan('[2]')} New Task ${chalk_1.default.cyan('[3]')} Payouts ${chalk_1.default.cyan('[4]')} Urgent ${chalk_1.default.cyan('[5]')} Smart ` + chalk_1.default.cyan('║'));
529
529
  console.log(chalk_1.default.cyan('║') + ' ' + chalk_1.default.cyan('║'));
530
530
  console.log(chalk_1.default.cyan('╚══════════════════════════════════════════════════════════════════════╝'));
531
531
  console.log('');
@@ -545,115 +545,68 @@ const showDashboard = async () => {
545
545
  // Silently fail - show basic prompt
546
546
  }
547
547
  };
548
- const runSmartQueueDirect = async () => {
549
- setTitle('Smart Queue');
550
- const spinner = (0, ora_1.default)('Loading queue...').start();
548
+ const runSuperSmartDirect = async () => {
549
+ setTitle('Super Smart');
550
+ const spinner = (0, ora_1.default)('Loading all pending payouts...').start();
551
551
  try {
552
- // Fetch metrics + all pending payouts in parallel
553
- const [metricsRes, payoutsRes, tarPayRes] = await Promise.all([
554
- api_1.api.getPayoutMetrics(),
552
+ // Fetch all pending payouts in parallel across all plans
553
+ const [payoutsRes, tarPayRes] = await Promise.all([
555
554
  api_1.api.listPayouts({ status: 'pending', limit: 500 }),
556
555
  api_1.api.getTarPayPayouts({ status: 'pending_review', limit: 500 }),
557
556
  ]);
558
- const metrics = metricsRes.data;
559
557
  const payouts = payoutsRes.data || [];
560
558
  const tarPayPayouts = tarPayRes.results || [];
561
559
  spinner.stop();
562
- // Build plan summary from regular payouts
563
- const byPlan = {};
564
- payouts.forEach((p) => {
565
- byPlan[p.plan] = (byPlan[p.plan] || 0) + 1;
566
- });
567
- // Add TarPay payouts
568
- tarPayPayouts.forEach((p) => {
569
- byPlan[p.plan] = (byPlan[p.plan] || 0) + 1;
570
- });
571
- const totalCount = payouts.length + tarPayPayouts.length;
572
- const planSummary = Object.entries(byPlan)
573
- .map(([plan, count]) => `${(PLAN_ICONS[plan] || '📋')} ${plan.toUpperCase()} ${count}`)
574
- .join(' ');
575
- // Show overview
576
- console.log('');
577
- console.log(chalk_1.default.cyan('╔═══ SMART QUEUE ═══╗'));
578
- console.log(chalk_1.default.cyan('║') + ` Pending: ${chalk_1.default.bold.yellow(String(totalCount))} payouts (${chalk_1.default.green('$' + metrics.pending_amount.toLocaleString())})`);
579
- console.log(chalk_1.default.cyan('║') + ` ${planSummary}`);
580
- console.log(chalk_1.default.cyan('╚═══════════════════╝'));
581
- console.log('');
582
- if (totalCount === 0) {
583
- console.log(chalk_1.default.green(' ✓ No pending payouts\n'));
584
- return;
585
- }
586
- // Step 1: Select plan (with back option)
587
- const planChoices = [
588
- { name: chalk_1.default.dim('← Back'), value: '__back__' },
589
- ...Object.entries(byPlan).map(([plan, count]) => ({
590
- name: `${PLAN_ICONS[plan] || '📋'} ${plan.charAt(0).toUpperCase() + plan.slice(1)} (${count})`,
591
- value: plan,
592
- })),
593
- { name: '📋 All Plans', value: '__all__' },
594
- ];
595
- const { selectedPlan } = await inquirer_1.default.prompt([
596
- {
597
- type: 'list',
598
- name: 'selectedPlan',
599
- message: 'Select plan:',
600
- choices: planChoices,
601
- },
602
- ]);
603
- if (selectedPlan === '__back__')
604
- return;
605
- const isTarPayPlan = selectedPlan === 'christmas';
606
- const planFilter = selectedPlan === '__all__' ? undefined : selectedPlan;
607
- let smartItems = [];
608
- if (isTarPayPlan) {
609
- smartItems = tarPayPayouts
610
- .filter((p) => !planFilter || p.plan === planFilter)
611
- .map((p) => ({
560
+ // Build unified list from both sources
561
+ const allItems = [
562
+ ...payouts.map((p) => ({
612
563
  id: p.id,
613
564
  user_email: p.user_email,
614
- crypto: p.currency,
615
- amount: parseFloat(p.amount),
616
- remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount),
565
+ crypto: p.crypto_type,
566
+ amount: p.amount,
567
+ remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : p.amount,
617
568
  has_partial_payments: p.has_partial_payments || false,
618
569
  paid_percentage: p.paid_percentage || 0,
619
- }));
620
- }
621
- else {
622
- smartItems = payouts
623
- .filter((p) => !planFilter || p.plan === planFilter)
624
- .map((p) => ({
570
+ plan: p.plan,
571
+ source: 'regular',
572
+ })),
573
+ ...tarPayPayouts.map((p) => ({
625
574
  id: p.id,
626
575
  user_email: p.user_email,
627
- crypto: p.crypto_type,
628
- amount: p.amount,
629
- remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : p.amount,
576
+ crypto: p.currency,
577
+ amount: parseFloat(p.amount),
578
+ remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount),
630
579
  has_partial_payments: p.has_partial_payments || false,
631
580
  paid_percentage: p.paid_percentage || 0,
632
- }));
633
- }
634
- if (smartItems.length === 0) {
635
- console.log(chalk_1.default.green('\n ✓ No pending payouts for this plan\n'));
636
- return;
637
- }
638
- // Group by currency
581
+ plan: p.plan,
582
+ source: 'tarpay',
583
+ })),
584
+ ];
585
+ // Group by currency across ALL plans
639
586
  const byCurrency = {};
640
- smartItems.forEach((p) => {
587
+ allItems.forEach((p) => {
641
588
  if (!byCurrency[p.crypto])
642
589
  byCurrency[p.crypto] = [];
643
590
  byCurrency[p.crypto].push(p);
644
591
  });
645
- const currencies = Object.keys(byCurrency);
646
- const planLabel = planFilter ? planFilter.toUpperCase() : 'ALL PLANS';
647
- const planColor = planFilter ? (PLAN_COLORS[planFilter] || chalk_1.default.white) : chalk_1.default.white;
648
- console.log('\n' + planColor(` 📋 ${planLabel} - Pending Payouts`));
649
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
650
- currencies.forEach((crypto) => {
651
- const items = byCurrency[crypto];
652
- const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
653
- console.log(` ${chalk_1.default.bold(crypto.padEnd(5))}: ${String(items.length).padStart(3)} payouts │ Total: ${chalk_1.default.green(formatAmount(total, crypto))}`);
654
- });
592
+ const totalCount = allItems.length;
593
+ const totalAmount = allItems.reduce((sum, p) => sum + p.remaining_amount, 0);
594
+ const currencySummary = Object.entries(byCurrency)
595
+ .map(([crypto, items]) => `${chalk_1.default.bold(crypto)} ${items.length}`)
596
+ .join(' ');
597
+ // Show overview
598
+ console.log('');
599
+ console.log(chalk_1.default.cyan('╔═══ SUPER SMART ═══╗'));
600
+ console.log(chalk_1.default.cyan('║') + ` Pending: ${chalk_1.default.bold.yellow(String(totalCount))} payouts (${chalk_1.default.green('$' + Math.round(totalAmount).toLocaleString())})`);
601
+ console.log(chalk_1.default.cyan('║') + ` ${currencySummary}`);
602
+ console.log(chalk_1.default.cyan('╚════════════════════╝'));
655
603
  console.log('');
656
- // Step 2: Select currency (with back, skip if only one)
604
+ if (totalCount === 0) {
605
+ console.log(chalk_1.default.green(' ✓ No pending payouts\n'));
606
+ return;
607
+ }
608
+ // Step 1: Select currency (with back option)
609
+ const currencies = Object.keys(byCurrency);
657
610
  let selectedCurrency;
658
611
  if (currencies.length === 1) {
659
612
  selectedCurrency = currencies[0];
@@ -671,7 +624,7 @@ const runSmartQueueDirect = async () => {
671
624
  {
672
625
  type: 'list',
673
626
  name: 'currency',
674
- message: 'Which currency to process?',
627
+ message: 'Select currency:',
675
628
  choices: currencyChoices,
676
629
  },
677
630
  ]);
@@ -680,8 +633,23 @@ const runSmartQueueDirect = async () => {
680
633
  selectedCurrency = currency;
681
634
  }
682
635
  const currencyItems = byCurrency[selectedCurrency];
636
+ // Show plan breakdown for selected currency
637
+ const byPlan = {};
638
+ currencyItems.forEach((p) => {
639
+ if (!byPlan[p.plan])
640
+ byPlan[p.plan] = [];
641
+ byPlan[p.plan].push(p);
642
+ });
643
+ console.log(`\n ${chalk_1.default.bold(selectedCurrency)} - ${currencyItems.length} payouts:`);
644
+ Object.entries(byPlan).forEach(([plan, items]) => {
645
+ const planTotal = items.reduce((sum, p) => sum + p.remaining_amount, 0);
646
+ const icon = PLAN_ICONS[plan] || '📋';
647
+ const color = PLAN_COLORS[plan] || chalk_1.default.white;
648
+ console.log(` ${icon} ${color(plan.toUpperCase().padEnd(12))} ${String(items.length).padStart(2)} │ ${chalk_1.default.green(formatAmount(planTotal, selectedCurrency))}`);
649
+ });
650
+ console.log('');
683
651
  const totalPending = currencyItems.reduce((sum, p) => sum + p.remaining_amount, 0);
684
- // Step 3: Ask available amount (with back)
652
+ // Step 2: Ask available amount (with back)
685
653
  const { availableAmount } = await inquirer_1.default.prompt([
686
654
  {
687
655
  type: 'input',
@@ -702,19 +670,32 @@ const runSmartQueueDirect = async () => {
702
670
  const available = parseFloat(availableAmount);
703
671
  const smartPercentage = Math.min((available / totalPending) * 100, 100);
704
672
  const roundedPct = Math.round(smartPercentage * 100) / 100;
705
- // Show preview
673
+ // Plan abbreviations for preview
674
+ const PLAN_ABBREV = {
675
+ hermes: 'HRM',
676
+ alpha: 'ALP',
677
+ mematic: 'MEM',
678
+ validator_v2: 'V2',
679
+ booster: 'BST',
680
+ dumpster: 'DMP',
681
+ christmas: 'XMS',
682
+ recovery: 'RCV',
683
+ };
684
+ // Show preview with plan labels
706
685
  console.log('\n' + chalk_1.default.cyan(` Processing ${chalk_1.default.bold(roundedPct + '%')} of ${currencyItems.length} ${selectedCurrency} payouts (${formatAmount(available, selectedCurrency)} / ${formatAmount(totalPending, selectedCurrency)})`));
707
686
  console.log(chalk_1.default.dim(' ─────────────────────────────'));
708
687
  let previewTotal = 0;
709
688
  currencyItems.forEach((p) => {
710
689
  const willPay = p.remaining_amount * (smartPercentage / 100);
711
690
  previewTotal += willPay;
712
- const email = p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email;
713
- console.log(` ${chalk_1.default.dim('#' + p.id)} ${email.padEnd(22)} ${formatAmount(p.remaining_amount, selectedCurrency).padStart(16)} → pays ${chalk_1.default.green(formatAmount(willPay, selectedCurrency))}`);
691
+ const email = p.user_email.length > 20 ? p.user_email.substring(0, 18) + '..' : p.user_email;
692
+ const abbrev = PLAN_ABBREV[p.plan] || p.plan.substring(0, 3).toUpperCase();
693
+ const planColor = PLAN_COLORS[p.plan] || chalk_1.default.white;
694
+ console.log(` ${chalk_1.default.dim('#' + p.id)} ${planColor('[' + abbrev + ']')} ${email.padEnd(20)} ${formatAmount(p.remaining_amount, selectedCurrency).padStart(14)} → pays ${chalk_1.default.green(formatAmount(willPay, selectedCurrency))}`);
714
695
  });
715
696
  console.log(chalk_1.default.dim(' ─────────────────────────────'));
716
697
  console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(previewTotal, selectedCurrency))}\n`));
717
- // Step 4: Confirm
698
+ // Step 3: Confirm
718
699
  const { confirmSmart } = await inquirer_1.default.prompt([
719
700
  {
720
701
  type: 'confirm',
@@ -724,12 +705,14 @@ const runSmartQueueDirect = async () => {
724
705
  },
725
706
  ]);
726
707
  if (confirmSmart) {
727
- const smartIds = currencyItems.map((p) => p.id);
728
- if (isTarPayPlan) {
729
- await processChristmasPayoutsWithProgress(smartIds, 'partial', roundedPct);
708
+ // Split by source for correct API calls
709
+ const regularIds = currencyItems.filter((p) => p.source === 'regular').map((p) => p.id);
710
+ const tarPayIds = currencyItems.filter((p) => p.source === 'tarpay').map((p) => p.id);
711
+ if (regularIds.length > 0) {
712
+ await processPayoutsWithProgress(regularIds, 'partial', roundedPct);
730
713
  }
731
- else {
732
- await processPayoutsWithProgress(smartIds, 'partial', roundedPct);
714
+ if (tarPayIds.length > 0) {
715
+ await processChristmasPayoutsWithProgress(tarPayIds, 'partial', roundedPct);
733
716
  }
734
717
  }
735
718
  else {
@@ -785,8 +768,8 @@ const runInteractiveShell = async () => {
785
768
  setTitle('Urgent');
786
769
  await showUrgentCmd();
787
770
  }
788
- else if (cmd === '5' || cmd === 'queue' || cmd === 'sq') {
789
- await runSmartQueueDirect();
771
+ else if (cmd === '5' || cmd === 'queue' || cmd === 'sq' || cmd === 'super' || cmd === 'ss') {
772
+ await runSuperSmartDirect();
790
773
  await showDashboard();
791
774
  }
792
775
  else {
@@ -1807,107 +1790,11 @@ const runChristmasPayoutsShell = async () => {
1807
1790
  }
1808
1791
  break;
1809
1792
  case 'smart':
1810
- case 'sp': {
1811
- // Smart partial: pay by available balance for Christmas
1812
- const xmasSmartSpinner = (0, ora_1.default)('Loading Christmas payouts...').start();
1813
- try {
1814
- const xmasData = await api_1.api.getTarPayPayouts({
1815
- plan: 'christmas',
1816
- status: 'pending_review',
1817
- limit: 500,
1818
- });
1819
- const xmasPayouts = xmasData.results || [];
1820
- xmasSmartSpinner.stop();
1821
- if (xmasPayouts.length === 0) {
1822
- console.log(chalk_1.default.green('\n ✓ No pending Christmas payouts\n'));
1823
- break;
1824
- }
1825
- // Group by currency
1826
- const xmasByCurrency = {};
1827
- xmasPayouts.forEach((p) => {
1828
- if (!xmasByCurrency[p.currency])
1829
- xmasByCurrency[p.currency] = [];
1830
- xmasByCurrency[p.currency].push(p);
1831
- });
1832
- const xmasCurrencies = Object.keys(xmasByCurrency);
1833
- console.log('\n' + chalk_1.default.red(` 🎄 CHRISTMAS - Pending Payouts`));
1834
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
1835
- xmasCurrencies.forEach((crypto) => {
1836
- const items = xmasByCurrency[crypto];
1837
- const total = items.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
1838
- console.log(` ${chalk_1.default.bold(crypto.padEnd(5))}: ${String(items.length).padStart(3)} payouts │ Total: ${chalk_1.default.green(formatAmount(total, crypto))}`);
1839
- });
1840
- console.log('');
1841
- let xmasCurrency;
1842
- if (xmasCurrencies.length === 1) {
1843
- xmasCurrency = xmasCurrencies[0];
1844
- }
1845
- else {
1846
- const { currency } = await inquirer_1.default.prompt([
1847
- {
1848
- type: 'list',
1849
- name: 'currency',
1850
- message: 'Which currency to process?',
1851
- choices: xmasCurrencies.map((c) => {
1852
- const items = xmasByCurrency[c];
1853
- const total = items.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
1854
- return { name: `${c} (${items.length} payouts, ${formatAmount(total, c)})`, value: c };
1855
- }),
1856
- },
1857
- ]);
1858
- xmasCurrency = currency;
1859
- }
1860
- const xmasCurrencyPayouts = xmasByCurrency[xmasCurrency];
1861
- const xmasTotalPending = xmasCurrencyPayouts.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
1862
- const { xmasAvailable } = await inquirer_1.default.prompt([
1863
- {
1864
- type: 'input',
1865
- name: 'xmasAvailable',
1866
- message: `How much ${xmasCurrency} do you have available? (total pending: ${formatAmount(xmasTotalPending, xmasCurrency)})`,
1867
- validate: (input) => {
1868
- const num = parseFloat(input);
1869
- if (isNaN(num) || num <= 0)
1870
- return 'Please enter a positive number';
1871
- return true;
1872
- },
1873
- },
1874
- ]);
1875
- const xmasAvailNum = parseFloat(xmasAvailable);
1876
- const xmasPct = Math.min((xmasAvailNum / xmasTotalPending) * 100, 100);
1877
- const xmasRoundedPct = Math.round(xmasPct * 100) / 100;
1878
- console.log('\n' + chalk_1.default.cyan(` Processing ${chalk_1.default.bold(xmasRoundedPct + '%')} of ${xmasCurrencyPayouts.length} ${xmasCurrency} payouts (${formatAmount(xmasAvailNum, xmasCurrency)} / ${formatAmount(xmasTotalPending, xmasCurrency)})`));
1879
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
1880
- let xmasPreviewTotal = 0;
1881
- xmasCurrencyPayouts.forEach((p) => {
1882
- const displayAmt = p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount);
1883
- const willPay = displayAmt * (xmasPct / 100);
1884
- xmasPreviewTotal += willPay;
1885
- const email = p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email;
1886
- console.log(` ${chalk_1.default.dim('#' + p.id)} ${email.padEnd(22)} ${formatAmount(displayAmt, xmasCurrency).padStart(16)} → pays ${chalk_1.default.green(formatAmount(willPay, xmasCurrency))}`);
1887
- });
1888
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
1889
- console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(xmasPreviewTotal, xmasCurrency))}\n`));
1890
- const { confirmXmasSmart } = await inquirer_1.default.prompt([
1891
- {
1892
- type: 'confirm',
1893
- name: 'confirmXmasSmart',
1894
- message: chalk_1.default.yellow(`⚠️ Pay ${xmasRoundedPct}% of ${xmasCurrencyPayouts.length} payout(s)?`),
1895
- default: false,
1896
- },
1897
- ]);
1898
- if (confirmXmasSmart) {
1899
- const xmasSmartIds = xmasCurrencyPayouts.map((p) => p.id);
1900
- await processChristmasPayoutsWithProgress(xmasSmartIds, 'partial', xmasRoundedPct);
1901
- }
1902
- else {
1903
- console.log(chalk_1.default.dim('\n Cancelled\n'));
1904
- }
1905
- }
1906
- catch (e) {
1907
- xmasSmartSpinner.fail(chalk_1.default.red('Failed to load Christmas payouts'));
1908
- }
1793
+ case 'sp':
1794
+ case 'super':
1795
+ case 'ss':
1796
+ await runSuperSmartDirect();
1909
1797
  break;
1910
- }
1911
1798
  case 'help':
1912
1799
  case '?':
1913
1800
  console.log(chalk_1.default.red('\n 🎄 Christmas Payout Commands:'));
@@ -1920,7 +1807,7 @@ const runChristmasPayoutsShell = async () => {
1920
1807
  console.log(' select, s Interactive selection mode');
1921
1808
  console.log(' approve, a Select & approve payouts');
1922
1809
  console.log(chalk_1.default.cyan(' partial, p Select & pay partial %'));
1923
- console.log(chalk_1.default.cyan(' smart, sp Smart partial: pay by available balance'));
1810
+ console.log(chalk_1.default.cyan(' smart, sp, ss Super Smart: pay by currency across all plans'));
1924
1811
  console.log(' reject Select & reject payouts');
1925
1812
  console.log(' back, q Return to main payouts');
1926
1813
  console.log(chalk_1.default.dim('\n Note: Payouts > $50 need approval, < $50 auto-sent'));
@@ -2106,162 +1993,9 @@ const runPayoutsShell = async () => {
2106
1993
  break;
2107
1994
  case 'smart':
2108
1995
  case 'sp':
2109
- // Smart partial: pay by available balance
2110
- const { smartPlan } = await inquirer_1.default.prompt([
2111
- {
2112
- type: 'list',
2113
- name: 'smartPlan',
2114
- message: 'Select plan:',
2115
- choices: [
2116
- { name: `${PLAN_ICONS.hermes || '⚡'} Hermes`, value: 'hermes' },
2117
- { name: `${PLAN_ICONS.alpha || '🔷'} Alpha`, value: 'alpha' },
2118
- { name: `${PLAN_ICONS.mematic || '💎'} Mematic`, value: 'mematic' },
2119
- { name: `${PLAN_ICONS.validator_v2 || '🔐'} Validator V2`, value: 'validator_v2' },
2120
- { name: `${PLAN_ICONS.booster || '🚀'} Booster`, value: 'booster' },
2121
- { name: `${PLAN_ICONS.christmas || '🎄'} Christmas`, value: 'christmas' },
2122
- { name: '🔄 Recovery', value: 'recovery' },
2123
- { name: '📋 All Plans', value: undefined },
2124
- ],
2125
- },
2126
- ]);
2127
- const isTarPayPlan = smartPlan === 'christmas';
2128
- const smartSpinner = (0, ora_1.default)('Loading pending payouts...').start();
2129
- try {
2130
- let smartItems = [];
2131
- if (isTarPayPlan) {
2132
- // TarPay payouts (Christmas, etc.)
2133
- const tarData = await api_1.api.getTarPayPayouts({
2134
- plan: smartPlan,
2135
- status: 'pending_review',
2136
- limit: 500,
2137
- });
2138
- const tarPayouts = tarData.results || [];
2139
- smartItems = tarPayouts.map((p) => ({
2140
- id: p.id,
2141
- user_email: p.user_email,
2142
- crypto: p.currency,
2143
- amount: parseFloat(p.amount),
2144
- remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount),
2145
- has_partial_payments: p.has_partial_payments || false,
2146
- paid_percentage: p.paid_percentage || 0,
2147
- }));
2148
- }
2149
- else {
2150
- // Regular payouts
2151
- const smartParams = { status: 'pending', limit: 500 };
2152
- if (smartPlan)
2153
- smartParams.plan = smartPlan;
2154
- const smartData = await api_1.api.listPayouts(smartParams);
2155
- const smartPayouts = smartData.data || [];
2156
- smartItems = smartPayouts.map((p) => ({
2157
- id: p.id,
2158
- user_email: p.user_email,
2159
- crypto: p.crypto_type,
2160
- amount: p.amount,
2161
- remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : p.amount,
2162
- has_partial_payments: p.has_partial_payments || false,
2163
- paid_percentage: p.paid_percentage || 0,
2164
- }));
2165
- }
2166
- smartSpinner.stop();
2167
- if (smartItems.length === 0) {
2168
- console.log(chalk_1.default.green('\n ✓ No pending payouts found\n'));
2169
- break;
2170
- }
2171
- // Group by crypto
2172
- const byCurrency = {};
2173
- smartItems.forEach((p) => {
2174
- if (!byCurrency[p.crypto])
2175
- byCurrency[p.crypto] = [];
2176
- byCurrency[p.crypto].push(p);
2177
- });
2178
- const currencies = Object.keys(byCurrency);
2179
- const planLabel = smartPlan ? smartPlan.toUpperCase() : 'ALL PLANS';
2180
- const planColor = smartPlan ? (PLAN_COLORS[smartPlan] || chalk_1.default.white) : chalk_1.default.white;
2181
- console.log('\n' + planColor(` 📋 ${planLabel} - Pending Payouts`));
2182
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
2183
- currencies.forEach((crypto) => {
2184
- const items = byCurrency[crypto];
2185
- const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
2186
- console.log(` ${chalk_1.default.bold(crypto.padEnd(5))}: ${String(items.length).padStart(3)} payouts │ Total: ${chalk_1.default.green(formatAmount(total, crypto))}`);
2187
- });
2188
- console.log('');
2189
- // Select currency
2190
- let selectedCurrency;
2191
- if (currencies.length === 1) {
2192
- selectedCurrency = currencies[0];
2193
- }
2194
- else {
2195
- const { currency } = await inquirer_1.default.prompt([
2196
- {
2197
- type: 'list',
2198
- name: 'currency',
2199
- message: 'Which currency to process?',
2200
- choices: currencies.map((c) => {
2201
- const items = byCurrency[c];
2202
- const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
2203
- return { name: `${c} (${items.length} payouts, ${formatAmount(total, c)})`, value: c };
2204
- }),
2205
- },
2206
- ]);
2207
- selectedCurrency = currency;
2208
- }
2209
- const currencyItems = byCurrency[selectedCurrency];
2210
- const totalPending = currencyItems.reduce((sum, p) => sum + p.remaining_amount, 0);
2211
- // Ask available amount
2212
- const { availableAmount } = await inquirer_1.default.prompt([
2213
- {
2214
- type: 'input',
2215
- name: 'availableAmount',
2216
- message: `How much ${selectedCurrency} do you have available? (total pending: ${formatAmount(totalPending, selectedCurrency)})`,
2217
- validate: (input) => {
2218
- const num = parseFloat(input);
2219
- if (isNaN(num) || num <= 0)
2220
- return 'Please enter a positive number';
2221
- return true;
2222
- },
2223
- },
2224
- ]);
2225
- const available = parseFloat(availableAmount);
2226
- const smartPercentage = Math.min((available / totalPending) * 100, 100);
2227
- const roundedPct = Math.round(smartPercentage * 100) / 100;
2228
- // Show breakdown
2229
- console.log('\n' + chalk_1.default.cyan(` Processing ${chalk_1.default.bold(roundedPct + '%')} of ${currencyItems.length} ${selectedCurrency} payouts (${formatAmount(available, selectedCurrency)} / ${formatAmount(totalPending, selectedCurrency)})`));
2230
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
2231
- let previewTotal = 0;
2232
- currencyItems.forEach((p) => {
2233
- const willPay = p.remaining_amount * (smartPercentage / 100);
2234
- previewTotal += willPay;
2235
- const email = p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email;
2236
- console.log(` ${chalk_1.default.dim('#' + p.id)} ${email.padEnd(22)} ${formatAmount(p.remaining_amount, selectedCurrency).padStart(16)} → pays ${chalk_1.default.green(formatAmount(willPay, selectedCurrency))}`);
2237
- });
2238
- console.log(chalk_1.default.dim(' ─────────────────────────────'));
2239
- console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(previewTotal, selectedCurrency))}\n`));
2240
- // Confirm
2241
- const { confirmSmart } = await inquirer_1.default.prompt([
2242
- {
2243
- type: 'confirm',
2244
- name: 'confirmSmart',
2245
- message: chalk_1.default.yellow(`⚠️ Pay ${roundedPct}% of ${currencyItems.length} payout(s)?`),
2246
- default: false,
2247
- },
2248
- ]);
2249
- if (confirmSmart) {
2250
- const smartIds = currencyItems.map((p) => p.id);
2251
- if (isTarPayPlan) {
2252
- await processChristmasPayoutsWithProgress(smartIds, 'partial', roundedPct);
2253
- }
2254
- else {
2255
- await processPayoutsWithProgress(smartIds, 'partial', roundedPct);
2256
- }
2257
- }
2258
- else {
2259
- console.log(chalk_1.default.dim('\n Cancelled\n'));
2260
- }
2261
- }
2262
- catch (e) {
2263
- smartSpinner.fail(chalk_1.default.red('Failed to load payouts'));
2264
- }
1996
+ case 'super':
1997
+ case 'ss':
1998
+ await runSuperSmartDirect();
2265
1999
  break;
2266
2000
  case 'hermes':
2267
2001
  case 'alpha':
@@ -2349,7 +2083,7 @@ const runPayoutsShell = async () => {
2349
2083
  console.log(' select [plan] Interactive payout selection');
2350
2084
  console.log(' approve [ids] Approve payouts (interactive if no IDs)');
2351
2085
  console.log(chalk_1.default.cyan(' partial, p Pay partial % (repayment mode)'));
2352
- console.log(chalk_1.default.cyan(' smart, sp Smart partial: pay by available balance'));
2086
+ console.log(chalk_1.default.cyan(' smart, sp, ss Super Smart: pay by currency across all plans'));
2353
2087
  console.log(chalk_1.default.yellow(' all Approve ALL pending payouts'));
2354
2088
  console.log(' cancel [ids] Cancel payouts (interactive if no IDs)');
2355
2089
  console.log(' process Process payouts by plan (interactive)');