@targlobal/mission-control 1.5.6 → 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 +194 -260
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +224 -285
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('│'));
|
|
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('║') + `
|
|
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,6 +545,185 @@ const showDashboard = async () => {
|
|
|
545
545
|
// Silently fail - show basic prompt
|
|
546
546
|
}
|
|
547
547
|
};
|
|
548
|
+
const runSuperSmartDirect = async () => {
|
|
549
|
+
setTitle('Super Smart');
|
|
550
|
+
const spinner = (0, ora_1.default)('Loading all pending payouts...').start();
|
|
551
|
+
try {
|
|
552
|
+
// Fetch all pending payouts in parallel across all plans
|
|
553
|
+
const [payoutsRes, tarPayRes] = await Promise.all([
|
|
554
|
+
api_1.api.listPayouts({ status: 'pending', limit: 500 }),
|
|
555
|
+
api_1.api.getTarPayPayouts({ status: 'pending_review', limit: 500 }),
|
|
556
|
+
]);
|
|
557
|
+
const payouts = payoutsRes.data || [];
|
|
558
|
+
const tarPayPayouts = tarPayRes.results || [];
|
|
559
|
+
spinner.stop();
|
|
560
|
+
// Build unified list from both sources
|
|
561
|
+
const allItems = [
|
|
562
|
+
...payouts.map((p) => ({
|
|
563
|
+
id: p.id,
|
|
564
|
+
user_email: p.user_email,
|
|
565
|
+
crypto: p.crypto_type,
|
|
566
|
+
amount: p.amount,
|
|
567
|
+
remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : p.amount,
|
|
568
|
+
has_partial_payments: p.has_partial_payments || false,
|
|
569
|
+
paid_percentage: p.paid_percentage || 0,
|
|
570
|
+
plan: p.plan,
|
|
571
|
+
source: 'regular',
|
|
572
|
+
})),
|
|
573
|
+
...tarPayPayouts.map((p) => ({
|
|
574
|
+
id: p.id,
|
|
575
|
+
user_email: p.user_email,
|
|
576
|
+
crypto: p.currency,
|
|
577
|
+
amount: parseFloat(p.amount),
|
|
578
|
+
remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount),
|
|
579
|
+
has_partial_payments: p.has_partial_payments || false,
|
|
580
|
+
paid_percentage: p.paid_percentage || 0,
|
|
581
|
+
plan: p.plan,
|
|
582
|
+
source: 'tarpay',
|
|
583
|
+
})),
|
|
584
|
+
];
|
|
585
|
+
// Group by currency across ALL plans
|
|
586
|
+
const byCurrency = {};
|
|
587
|
+
allItems.forEach((p) => {
|
|
588
|
+
if (!byCurrency[p.crypto])
|
|
589
|
+
byCurrency[p.crypto] = [];
|
|
590
|
+
byCurrency[p.crypto].push(p);
|
|
591
|
+
});
|
|
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('╚════════════════════╝'));
|
|
603
|
+
console.log('');
|
|
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);
|
|
610
|
+
let selectedCurrency;
|
|
611
|
+
if (currencies.length === 1) {
|
|
612
|
+
selectedCurrency = currencies[0];
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
const currencyChoices = [
|
|
616
|
+
{ name: chalk_1.default.dim('← Back'), value: '__back__' },
|
|
617
|
+
...currencies.map((c) => {
|
|
618
|
+
const items = byCurrency[c];
|
|
619
|
+
const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
|
|
620
|
+
return { name: `${c} (${items.length} payouts, ${formatAmount(total, c)})`, value: c };
|
|
621
|
+
}),
|
|
622
|
+
];
|
|
623
|
+
const { currency } = await inquirer_1.default.prompt([
|
|
624
|
+
{
|
|
625
|
+
type: 'list',
|
|
626
|
+
name: 'currency',
|
|
627
|
+
message: 'Select currency:',
|
|
628
|
+
choices: currencyChoices,
|
|
629
|
+
},
|
|
630
|
+
]);
|
|
631
|
+
if (currency === '__back__')
|
|
632
|
+
return;
|
|
633
|
+
selectedCurrency = currency;
|
|
634
|
+
}
|
|
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('');
|
|
651
|
+
const totalPending = currencyItems.reduce((sum, p) => sum + p.remaining_amount, 0);
|
|
652
|
+
// Step 2: Ask available amount (with back)
|
|
653
|
+
const { availableAmount } = await inquirer_1.default.prompt([
|
|
654
|
+
{
|
|
655
|
+
type: 'input',
|
|
656
|
+
name: 'availableAmount',
|
|
657
|
+
message: `How much ${selectedCurrency} available? (pending: ${formatAmount(totalPending, selectedCurrency)})`,
|
|
658
|
+
validate: (input) => {
|
|
659
|
+
if (input.toLowerCase() === 'back' || input.toLowerCase() === 'q')
|
|
660
|
+
return true;
|
|
661
|
+
const num = parseFloat(input);
|
|
662
|
+
if (isNaN(num) || num <= 0)
|
|
663
|
+
return 'Enter a positive number (or "back" to go back)';
|
|
664
|
+
return true;
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
]);
|
|
668
|
+
if (availableAmount.toLowerCase() === 'back' || availableAmount.toLowerCase() === 'q')
|
|
669
|
+
return;
|
|
670
|
+
const available = parseFloat(availableAmount);
|
|
671
|
+
const smartPercentage = Math.min((available / totalPending) * 100, 100);
|
|
672
|
+
const roundedPct = Math.round(smartPercentage * 100) / 100;
|
|
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
|
|
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)})`));
|
|
686
|
+
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
687
|
+
let previewTotal = 0;
|
|
688
|
+
currencyItems.forEach((p) => {
|
|
689
|
+
const willPay = p.remaining_amount * (smartPercentage / 100);
|
|
690
|
+
previewTotal += willPay;
|
|
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))}`);
|
|
695
|
+
});
|
|
696
|
+
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
697
|
+
console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(previewTotal, selectedCurrency))}\n`));
|
|
698
|
+
// Step 3: Confirm
|
|
699
|
+
const { confirmSmart } = await inquirer_1.default.prompt([
|
|
700
|
+
{
|
|
701
|
+
type: 'confirm',
|
|
702
|
+
name: 'confirmSmart',
|
|
703
|
+
message: chalk_1.default.yellow(`⚠️ Pay ${roundedPct}% of ${currencyItems.length} payout(s)?`),
|
|
704
|
+
default: false,
|
|
705
|
+
},
|
|
706
|
+
]);
|
|
707
|
+
if (confirmSmart) {
|
|
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);
|
|
713
|
+
}
|
|
714
|
+
if (tarPayIds.length > 0) {
|
|
715
|
+
await processChristmasPayoutsWithProgress(tarPayIds, 'partial', roundedPct);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
else {
|
|
719
|
+
console.log(chalk_1.default.dim('\n Cancelled\n'));
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
catch (e) {
|
|
723
|
+
spinner.stop();
|
|
724
|
+
console.log(chalk_1.default.red(` Error: ${e.message}\n`));
|
|
725
|
+
}
|
|
726
|
+
};
|
|
548
727
|
const runInteractiveShell = async () => {
|
|
549
728
|
setTitle('Mission Control');
|
|
550
729
|
await showDashboard();
|
|
@@ -589,6 +768,10 @@ const runInteractiveShell = async () => {
|
|
|
589
768
|
setTitle('Urgent');
|
|
590
769
|
await showUrgentCmd();
|
|
591
770
|
}
|
|
771
|
+
else if (cmd === '5' || cmd === 'queue' || cmd === 'sq' || cmd === 'super' || cmd === 'ss') {
|
|
772
|
+
await runSuperSmartDirect();
|
|
773
|
+
await showDashboard();
|
|
774
|
+
}
|
|
592
775
|
else {
|
|
593
776
|
// Regular commands
|
|
594
777
|
switch (mainCmd) {
|
|
@@ -1607,107 +1790,11 @@ const runChristmasPayoutsShell = async () => {
|
|
|
1607
1790
|
}
|
|
1608
1791
|
break;
|
|
1609
1792
|
case 'smart':
|
|
1610
|
-
case 'sp':
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
const xmasData = await api_1.api.getTarPayPayouts({
|
|
1615
|
-
plan: 'christmas',
|
|
1616
|
-
status: 'pending_review',
|
|
1617
|
-
limit: 500,
|
|
1618
|
-
});
|
|
1619
|
-
const xmasPayouts = xmasData.results || [];
|
|
1620
|
-
xmasSmartSpinner.stop();
|
|
1621
|
-
if (xmasPayouts.length === 0) {
|
|
1622
|
-
console.log(chalk_1.default.green('\n ✓ No pending Christmas payouts\n'));
|
|
1623
|
-
break;
|
|
1624
|
-
}
|
|
1625
|
-
// Group by currency
|
|
1626
|
-
const xmasByCurrency = {};
|
|
1627
|
-
xmasPayouts.forEach((p) => {
|
|
1628
|
-
if (!xmasByCurrency[p.currency])
|
|
1629
|
-
xmasByCurrency[p.currency] = [];
|
|
1630
|
-
xmasByCurrency[p.currency].push(p);
|
|
1631
|
-
});
|
|
1632
|
-
const xmasCurrencies = Object.keys(xmasByCurrency);
|
|
1633
|
-
console.log('\n' + chalk_1.default.red(` 🎄 CHRISTMAS - Pending Payouts`));
|
|
1634
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
1635
|
-
xmasCurrencies.forEach((crypto) => {
|
|
1636
|
-
const items = xmasByCurrency[crypto];
|
|
1637
|
-
const total = items.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
|
|
1638
|
-
console.log(` ${chalk_1.default.bold(crypto.padEnd(5))}: ${String(items.length).padStart(3)} payouts │ Total: ${chalk_1.default.green(formatAmount(total, crypto))}`);
|
|
1639
|
-
});
|
|
1640
|
-
console.log('');
|
|
1641
|
-
let xmasCurrency;
|
|
1642
|
-
if (xmasCurrencies.length === 1) {
|
|
1643
|
-
xmasCurrency = xmasCurrencies[0];
|
|
1644
|
-
}
|
|
1645
|
-
else {
|
|
1646
|
-
const { currency } = await inquirer_1.default.prompt([
|
|
1647
|
-
{
|
|
1648
|
-
type: 'list',
|
|
1649
|
-
name: 'currency',
|
|
1650
|
-
message: 'Which currency to process?',
|
|
1651
|
-
choices: xmasCurrencies.map((c) => {
|
|
1652
|
-
const items = xmasByCurrency[c];
|
|
1653
|
-
const total = items.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
|
|
1654
|
-
return { name: `${c} (${items.length} payouts, ${formatAmount(total, c)})`, value: c };
|
|
1655
|
-
}),
|
|
1656
|
-
},
|
|
1657
|
-
]);
|
|
1658
|
-
xmasCurrency = currency;
|
|
1659
|
-
}
|
|
1660
|
-
const xmasCurrencyPayouts = xmasByCurrency[xmasCurrency];
|
|
1661
|
-
const xmasTotalPending = xmasCurrencyPayouts.reduce((sum, p) => sum + (p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount)), 0);
|
|
1662
|
-
const { xmasAvailable } = await inquirer_1.default.prompt([
|
|
1663
|
-
{
|
|
1664
|
-
type: 'input',
|
|
1665
|
-
name: 'xmasAvailable',
|
|
1666
|
-
message: `How much ${xmasCurrency} do you have available? (total pending: ${formatAmount(xmasTotalPending, xmasCurrency)})`,
|
|
1667
|
-
validate: (input) => {
|
|
1668
|
-
const num = parseFloat(input);
|
|
1669
|
-
if (isNaN(num) || num <= 0)
|
|
1670
|
-
return 'Please enter a positive number';
|
|
1671
|
-
return true;
|
|
1672
|
-
},
|
|
1673
|
-
},
|
|
1674
|
-
]);
|
|
1675
|
-
const xmasAvailNum = parseFloat(xmasAvailable);
|
|
1676
|
-
const xmasPct = Math.min((xmasAvailNum / xmasTotalPending) * 100, 100);
|
|
1677
|
-
const xmasRoundedPct = Math.round(xmasPct * 100) / 100;
|
|
1678
|
-
console.log('\n' + chalk_1.default.cyan(` Processing ${chalk_1.default.bold(xmasRoundedPct + '%')} of ${xmasCurrencyPayouts.length} ${xmasCurrency} payouts (${formatAmount(xmasAvailNum, xmasCurrency)} / ${formatAmount(xmasTotalPending, xmasCurrency)})`));
|
|
1679
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
1680
|
-
let xmasPreviewTotal = 0;
|
|
1681
|
-
xmasCurrencyPayouts.forEach((p) => {
|
|
1682
|
-
const displayAmt = p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount);
|
|
1683
|
-
const willPay = displayAmt * (xmasPct / 100);
|
|
1684
|
-
xmasPreviewTotal += willPay;
|
|
1685
|
-
const email = p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email;
|
|
1686
|
-
console.log(` ${chalk_1.default.dim('#' + p.id)} ${email.padEnd(22)} ${formatAmount(displayAmt, xmasCurrency).padStart(16)} → pays ${chalk_1.default.green(formatAmount(willPay, xmasCurrency))}`);
|
|
1687
|
-
});
|
|
1688
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
1689
|
-
console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(xmasPreviewTotal, xmasCurrency))}\n`));
|
|
1690
|
-
const { confirmXmasSmart } = await inquirer_1.default.prompt([
|
|
1691
|
-
{
|
|
1692
|
-
type: 'confirm',
|
|
1693
|
-
name: 'confirmXmasSmart',
|
|
1694
|
-
message: chalk_1.default.yellow(`⚠️ Pay ${xmasRoundedPct}% of ${xmasCurrencyPayouts.length} payout(s)?`),
|
|
1695
|
-
default: false,
|
|
1696
|
-
},
|
|
1697
|
-
]);
|
|
1698
|
-
if (confirmXmasSmart) {
|
|
1699
|
-
const xmasSmartIds = xmasCurrencyPayouts.map((p) => p.id);
|
|
1700
|
-
await processChristmasPayoutsWithProgress(xmasSmartIds, 'partial', xmasRoundedPct);
|
|
1701
|
-
}
|
|
1702
|
-
else {
|
|
1703
|
-
console.log(chalk_1.default.dim('\n Cancelled\n'));
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
catch (e) {
|
|
1707
|
-
xmasSmartSpinner.fail(chalk_1.default.red('Failed to load Christmas payouts'));
|
|
1708
|
-
}
|
|
1793
|
+
case 'sp':
|
|
1794
|
+
case 'super':
|
|
1795
|
+
case 'ss':
|
|
1796
|
+
await runSuperSmartDirect();
|
|
1709
1797
|
break;
|
|
1710
|
-
}
|
|
1711
1798
|
case 'help':
|
|
1712
1799
|
case '?':
|
|
1713
1800
|
console.log(chalk_1.default.red('\n 🎄 Christmas Payout Commands:'));
|
|
@@ -1720,7 +1807,7 @@ const runChristmasPayoutsShell = async () => {
|
|
|
1720
1807
|
console.log(' select, s Interactive selection mode');
|
|
1721
1808
|
console.log(' approve, a Select & approve payouts');
|
|
1722
1809
|
console.log(chalk_1.default.cyan(' partial, p Select & pay partial %'));
|
|
1723
|
-
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'));
|
|
1724
1811
|
console.log(' reject Select & reject payouts');
|
|
1725
1812
|
console.log(' back, q Return to main payouts');
|
|
1726
1813
|
console.log(chalk_1.default.dim('\n Note: Payouts > $50 need approval, < $50 auto-sent'));
|
|
@@ -1906,162 +1993,9 @@ const runPayoutsShell = async () => {
|
|
|
1906
1993
|
break;
|
|
1907
1994
|
case 'smart':
|
|
1908
1995
|
case 'sp':
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
type: 'list',
|
|
1913
|
-
name: 'smartPlan',
|
|
1914
|
-
message: 'Select plan:',
|
|
1915
|
-
choices: [
|
|
1916
|
-
{ name: `${PLAN_ICONS.hermes || '⚡'} Hermes`, value: 'hermes' },
|
|
1917
|
-
{ name: `${PLAN_ICONS.alpha || '🔷'} Alpha`, value: 'alpha' },
|
|
1918
|
-
{ name: `${PLAN_ICONS.mematic || '💎'} Mematic`, value: 'mematic' },
|
|
1919
|
-
{ name: `${PLAN_ICONS.validator_v2 || '🔐'} Validator V2`, value: 'validator_v2' },
|
|
1920
|
-
{ name: `${PLAN_ICONS.booster || '🚀'} Booster`, value: 'booster' },
|
|
1921
|
-
{ name: `${PLAN_ICONS.christmas || '🎄'} Christmas`, value: 'christmas' },
|
|
1922
|
-
{ name: '🔄 Recovery', value: 'recovery' },
|
|
1923
|
-
{ name: '📋 All Plans', value: undefined },
|
|
1924
|
-
],
|
|
1925
|
-
},
|
|
1926
|
-
]);
|
|
1927
|
-
const isTarPayPlan = smartPlan === 'christmas';
|
|
1928
|
-
const smartSpinner = (0, ora_1.default)('Loading pending payouts...').start();
|
|
1929
|
-
try {
|
|
1930
|
-
let smartItems = [];
|
|
1931
|
-
if (isTarPayPlan) {
|
|
1932
|
-
// TarPay payouts (Christmas, etc.)
|
|
1933
|
-
const tarData = await api_1.api.getTarPayPayouts({
|
|
1934
|
-
plan: smartPlan,
|
|
1935
|
-
status: 'pending_review',
|
|
1936
|
-
limit: 500,
|
|
1937
|
-
});
|
|
1938
|
-
const tarPayouts = tarData.results || [];
|
|
1939
|
-
smartItems = tarPayouts.map((p) => ({
|
|
1940
|
-
id: p.id,
|
|
1941
|
-
user_email: p.user_email,
|
|
1942
|
-
crypto: p.currency,
|
|
1943
|
-
amount: parseFloat(p.amount),
|
|
1944
|
-
remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : parseFloat(p.amount),
|
|
1945
|
-
has_partial_payments: p.has_partial_payments || false,
|
|
1946
|
-
paid_percentage: p.paid_percentage || 0,
|
|
1947
|
-
}));
|
|
1948
|
-
}
|
|
1949
|
-
else {
|
|
1950
|
-
// Regular payouts
|
|
1951
|
-
const smartParams = { status: 'pending', limit: 500 };
|
|
1952
|
-
if (smartPlan)
|
|
1953
|
-
smartParams.plan = smartPlan;
|
|
1954
|
-
const smartData = await api_1.api.listPayouts(smartParams);
|
|
1955
|
-
const smartPayouts = smartData.data || [];
|
|
1956
|
-
smartItems = smartPayouts.map((p) => ({
|
|
1957
|
-
id: p.id,
|
|
1958
|
-
user_email: p.user_email,
|
|
1959
|
-
crypto: p.crypto_type,
|
|
1960
|
-
amount: p.amount,
|
|
1961
|
-
remaining_amount: p.remaining_amount !== undefined ? p.remaining_amount : p.amount,
|
|
1962
|
-
has_partial_payments: p.has_partial_payments || false,
|
|
1963
|
-
paid_percentage: p.paid_percentage || 0,
|
|
1964
|
-
}));
|
|
1965
|
-
}
|
|
1966
|
-
smartSpinner.stop();
|
|
1967
|
-
if (smartItems.length === 0) {
|
|
1968
|
-
console.log(chalk_1.default.green('\n ✓ No pending payouts found\n'));
|
|
1969
|
-
break;
|
|
1970
|
-
}
|
|
1971
|
-
// Group by crypto
|
|
1972
|
-
const byCurrency = {};
|
|
1973
|
-
smartItems.forEach((p) => {
|
|
1974
|
-
if (!byCurrency[p.crypto])
|
|
1975
|
-
byCurrency[p.crypto] = [];
|
|
1976
|
-
byCurrency[p.crypto].push(p);
|
|
1977
|
-
});
|
|
1978
|
-
const currencies = Object.keys(byCurrency);
|
|
1979
|
-
const planLabel = smartPlan ? smartPlan.toUpperCase() : 'ALL PLANS';
|
|
1980
|
-
const planColor = smartPlan ? (PLAN_COLORS[smartPlan] || chalk_1.default.white) : chalk_1.default.white;
|
|
1981
|
-
console.log('\n' + planColor(` 📋 ${planLabel} - Pending Payouts`));
|
|
1982
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
1983
|
-
currencies.forEach((crypto) => {
|
|
1984
|
-
const items = byCurrency[crypto];
|
|
1985
|
-
const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
|
|
1986
|
-
console.log(` ${chalk_1.default.bold(crypto.padEnd(5))}: ${String(items.length).padStart(3)} payouts │ Total: ${chalk_1.default.green(formatAmount(total, crypto))}`);
|
|
1987
|
-
});
|
|
1988
|
-
console.log('');
|
|
1989
|
-
// Select currency
|
|
1990
|
-
let selectedCurrency;
|
|
1991
|
-
if (currencies.length === 1) {
|
|
1992
|
-
selectedCurrency = currencies[0];
|
|
1993
|
-
}
|
|
1994
|
-
else {
|
|
1995
|
-
const { currency } = await inquirer_1.default.prompt([
|
|
1996
|
-
{
|
|
1997
|
-
type: 'list',
|
|
1998
|
-
name: 'currency',
|
|
1999
|
-
message: 'Which currency to process?',
|
|
2000
|
-
choices: currencies.map((c) => {
|
|
2001
|
-
const items = byCurrency[c];
|
|
2002
|
-
const total = items.reduce((sum, p) => sum + p.remaining_amount, 0);
|
|
2003
|
-
return { name: `${c} (${items.length} payouts, ${formatAmount(total, c)})`, value: c };
|
|
2004
|
-
}),
|
|
2005
|
-
},
|
|
2006
|
-
]);
|
|
2007
|
-
selectedCurrency = currency;
|
|
2008
|
-
}
|
|
2009
|
-
const currencyItems = byCurrency[selectedCurrency];
|
|
2010
|
-
const totalPending = currencyItems.reduce((sum, p) => sum + p.remaining_amount, 0);
|
|
2011
|
-
// Ask available amount
|
|
2012
|
-
const { availableAmount } = await inquirer_1.default.prompt([
|
|
2013
|
-
{
|
|
2014
|
-
type: 'input',
|
|
2015
|
-
name: 'availableAmount',
|
|
2016
|
-
message: `How much ${selectedCurrency} do you have available? (total pending: ${formatAmount(totalPending, selectedCurrency)})`,
|
|
2017
|
-
validate: (input) => {
|
|
2018
|
-
const num = parseFloat(input);
|
|
2019
|
-
if (isNaN(num) || num <= 0)
|
|
2020
|
-
return 'Please enter a positive number';
|
|
2021
|
-
return true;
|
|
2022
|
-
},
|
|
2023
|
-
},
|
|
2024
|
-
]);
|
|
2025
|
-
const available = parseFloat(availableAmount);
|
|
2026
|
-
const smartPercentage = Math.min((available / totalPending) * 100, 100);
|
|
2027
|
-
const roundedPct = Math.round(smartPercentage * 100) / 100;
|
|
2028
|
-
// Show breakdown
|
|
2029
|
-
console.log('\n' + chalk_1.default.cyan(` Processing ${chalk_1.default.bold(roundedPct + '%')} of ${currencyItems.length} ${selectedCurrency} payouts (${formatAmount(available, selectedCurrency)} / ${formatAmount(totalPending, selectedCurrency)})`));
|
|
2030
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
2031
|
-
let previewTotal = 0;
|
|
2032
|
-
currencyItems.forEach((p) => {
|
|
2033
|
-
const willPay = p.remaining_amount * (smartPercentage / 100);
|
|
2034
|
-
previewTotal += willPay;
|
|
2035
|
-
const email = p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email;
|
|
2036
|
-
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))}`);
|
|
2037
|
-
});
|
|
2038
|
-
console.log(chalk_1.default.dim(' ─────────────────────────────'));
|
|
2039
|
-
console.log(chalk_1.default.bold(` Total to send: ${chalk_1.default.green(formatAmount(previewTotal, selectedCurrency))}\n`));
|
|
2040
|
-
// Confirm
|
|
2041
|
-
const { confirmSmart } = await inquirer_1.default.prompt([
|
|
2042
|
-
{
|
|
2043
|
-
type: 'confirm',
|
|
2044
|
-
name: 'confirmSmart',
|
|
2045
|
-
message: chalk_1.default.yellow(`⚠️ Pay ${roundedPct}% of ${currencyItems.length} payout(s)?`),
|
|
2046
|
-
default: false,
|
|
2047
|
-
},
|
|
2048
|
-
]);
|
|
2049
|
-
if (confirmSmart) {
|
|
2050
|
-
const smartIds = currencyItems.map((p) => p.id);
|
|
2051
|
-
if (isTarPayPlan) {
|
|
2052
|
-
await processChristmasPayoutsWithProgress(smartIds, 'partial', roundedPct);
|
|
2053
|
-
}
|
|
2054
|
-
else {
|
|
2055
|
-
await processPayoutsWithProgress(smartIds, 'partial', roundedPct);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
else {
|
|
2059
|
-
console.log(chalk_1.default.dim('\n Cancelled\n'));
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
catch (e) {
|
|
2063
|
-
smartSpinner.fail(chalk_1.default.red('Failed to load payouts'));
|
|
2064
|
-
}
|
|
1996
|
+
case 'super':
|
|
1997
|
+
case 'ss':
|
|
1998
|
+
await runSuperSmartDirect();
|
|
2065
1999
|
break;
|
|
2066
2000
|
case 'hermes':
|
|
2067
2001
|
case 'alpha':
|
|
@@ -2149,7 +2083,7 @@ const runPayoutsShell = async () => {
|
|
|
2149
2083
|
console.log(' select [plan] Interactive payout selection');
|
|
2150
2084
|
console.log(' approve [ids] Approve payouts (interactive if no IDs)');
|
|
2151
2085
|
console.log(chalk_1.default.cyan(' partial, p Pay partial % (repayment mode)'));
|
|
2152
|
-
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'));
|
|
2153
2087
|
console.log(chalk_1.default.yellow(' all Approve ALL pending payouts'));
|
|
2154
2088
|
console.log(' cancel [ids] Cancel payouts (interactive if no IDs)');
|
|
2155
2089
|
console.log(' process Process payouts by plan (interactive)');
|