@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 +95 -361
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +117 -407
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]')}
|
|
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]')}
|
|
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
|
|
549
|
-
setTitle('Smart
|
|
550
|
-
const spinner = (0, ora_1.default)('Loading
|
|
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
|
|
553
|
-
const [
|
|
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
|
|
563
|
-
const
|
|
564
|
-
|
|
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.
|
|
615
|
-
amount:
|
|
616
|
-
remaining_amount: p.remaining_amount !== undefined ? p.remaining_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
|
-
|
|
622
|
-
|
|
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.
|
|
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
|
-
|
|
635
|
-
|
|
636
|
-
|
|
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
|
-
|
|
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
|
|
646
|
-
const
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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
|
-
|
|
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: '
|
|
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
|
|
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
|
-
//
|
|
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 >
|
|
713
|
-
|
|
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
|
|
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
|
-
|
|
728
|
-
|
|
729
|
-
|
|
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
|
-
|
|
732
|
-
await
|
|
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
|
|
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
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
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
|
|
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
|
-
|
|
2110
|
-
|
|
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
|
|
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)');
|