@targlobal/mission-control 1.3.2 → 1.4.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/dist/api.d.ts +34 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +25 -0
- package/dist/api.js.map +1 -1
- package/dist/index.js +485 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +57 -0
- package/src/index.ts +510 -54
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
45
45
|
const config_1 = require("./config");
|
|
46
46
|
const api_1 = require("./api");
|
|
47
47
|
const child_process_1 = require("child_process");
|
|
48
|
-
const VERSION = '1.
|
|
48
|
+
const VERSION = '1.4.0';
|
|
49
49
|
const program = new commander_1.Command();
|
|
50
50
|
// Set terminal title
|
|
51
51
|
const setTitle = (context) => {
|
|
@@ -705,6 +705,7 @@ const PLAN_COLORS = {
|
|
|
705
705
|
validator_v2: chalk_1.default.blue,
|
|
706
706
|
booster: chalk_1.default.green,
|
|
707
707
|
dumpster: chalk_1.default.gray,
|
|
708
|
+
christmas: chalk_1.default.red,
|
|
708
709
|
};
|
|
709
710
|
const PLAN_ICONS = {
|
|
710
711
|
hermes: '⚡',
|
|
@@ -713,6 +714,43 @@ const PLAN_ICONS = {
|
|
|
713
714
|
validator_v2: '🔐',
|
|
714
715
|
booster: '🚀',
|
|
715
716
|
dumpster: '🗑️',
|
|
717
|
+
christmas: '🎄',
|
|
718
|
+
};
|
|
719
|
+
// Helper to get percentage (preset or custom input)
|
|
720
|
+
const getPercentageWithCustom = async () => {
|
|
721
|
+
const { percentage } = await inquirer_1.default.prompt([
|
|
722
|
+
{
|
|
723
|
+
type: 'list',
|
|
724
|
+
name: 'percentage',
|
|
725
|
+
message: 'Select percentage of remaining amount to pay:',
|
|
726
|
+
choices: [
|
|
727
|
+
{ name: '10%', value: 10 },
|
|
728
|
+
{ name: '25%', value: 25 },
|
|
729
|
+
{ name: '50%', value: 50 },
|
|
730
|
+
{ name: '75%', value: 75 },
|
|
731
|
+
{ name: '100% (Full)', value: 100 },
|
|
732
|
+
{ name: chalk_1.default.cyan('Custom...'), value: -1 },
|
|
733
|
+
],
|
|
734
|
+
},
|
|
735
|
+
]);
|
|
736
|
+
if (percentage === -1) {
|
|
737
|
+
const { customPct } = await inquirer_1.default.prompt([
|
|
738
|
+
{
|
|
739
|
+
type: 'input',
|
|
740
|
+
name: 'customPct',
|
|
741
|
+
message: 'Enter custom percentage (1-100):',
|
|
742
|
+
validate: (input) => {
|
|
743
|
+
const num = parseFloat(input);
|
|
744
|
+
if (isNaN(num) || num < 1 || num > 100) {
|
|
745
|
+
return 'Please enter a number between 1 and 100';
|
|
746
|
+
}
|
|
747
|
+
return true;
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
]);
|
|
751
|
+
return parseFloat(customPct);
|
|
752
|
+
}
|
|
753
|
+
return percentage;
|
|
716
754
|
};
|
|
717
755
|
const formatAmount = (amount, crypto) => {
|
|
718
756
|
const formatted = amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 4 });
|
|
@@ -811,12 +849,13 @@ const showPayoutDashboard = async () => {
|
|
|
811
849
|
Object.entries(byPlan).forEach(([plan, planPayouts]) => {
|
|
812
850
|
const planColor = PLAN_COLORS[plan] || chalk_1.default.white;
|
|
813
851
|
const planIcon = PLAN_ICONS[plan] || '📋';
|
|
814
|
-
// Group amounts by crypto type
|
|
852
|
+
// Group REMAINING amounts by crypto type (use remaining_amount if partial, else amount)
|
|
815
853
|
const byCrypto = {};
|
|
816
854
|
planPayouts.forEach((p) => {
|
|
817
855
|
if (!byCrypto[p.crypto_type])
|
|
818
856
|
byCrypto[p.crypto_type] = 0;
|
|
819
|
-
|
|
857
|
+
const displayAmt = p.remaining_amount !== undefined ? p.remaining_amount : p.amount;
|
|
858
|
+
byCrypto[p.crypto_type] += displayAmt;
|
|
820
859
|
});
|
|
821
860
|
const cryptoTotals = Object.entries(byCrypto).map(([crypto, amt]) => `${amt.toFixed(2)} ${crypto}`).join(', ');
|
|
822
861
|
console.log(chalk_1.default.cyan('║') + ` ${planIcon} ${planColor(plan.toUpperCase().padEnd(12))} ${chalk_1.default.dim('|')} ${chalk_1.default.white(planPayouts.length + ' payouts')} ${chalk_1.default.dim('|')} ${chalk_1.default.yellow(cryptoTotals)}`.padEnd(72) + chalk_1.default.cyan('║'));
|
|
@@ -824,9 +863,11 @@ const showPayoutDashboard = async () => {
|
|
|
824
863
|
planPayouts.slice(0, 3).forEach((p) => {
|
|
825
864
|
const idStr = chalk_1.default.dim(`#${p.id}`);
|
|
826
865
|
const emailStr = p.user_email.length > 20 ? p.user_email.substring(0, 18) + '..' : p.user_email;
|
|
827
|
-
const
|
|
866
|
+
const displayAmt = p.remaining_amount !== undefined ? p.remaining_amount : p.amount;
|
|
867
|
+
const amountStr = formatAmount(displayAmt, p.crypto_type);
|
|
868
|
+
const pctStr = p.has_partial_payments && (p.paid_percentage || 0) > 0 ? chalk_1.default.cyan(` (${Math.round(p.paid_percentage || 0)}%)`) : '';
|
|
828
869
|
const walletStr = formatWallet(p.wallet_address);
|
|
829
|
-
console.log(chalk_1.default.cyan('║') + ` ${idStr} ${chalk_1.default.white(emailStr.padEnd(20))} ${chalk_1.default.green(amountStr.padStart(
|
|
870
|
+
console.log(chalk_1.default.cyan('║') + ` ${idStr} ${chalk_1.default.white(emailStr.padEnd(20))} ${chalk_1.default.green(amountStr.padStart(10))}${pctStr} ${chalk_1.default.dim(walletStr)}`.padEnd(72) + chalk_1.default.cyan('║'));
|
|
830
871
|
});
|
|
831
872
|
if (planPayouts.length > 3) {
|
|
832
873
|
console.log(chalk_1.default.cyan('║') + chalk_1.default.dim(` ... and ${planPayouts.length - 3} more`).padEnd(64) + chalk_1.default.cyan('║'));
|
|
@@ -1179,6 +1220,413 @@ const processPayoutsWithProgress = async (ids, action, percentage) => {
|
|
|
1179
1220
|
return { success: false };
|
|
1180
1221
|
}
|
|
1181
1222
|
};
|
|
1223
|
+
// ==================== CHRISTMAS/TARPAY PAYOUT FUNCTIONS ====================
|
|
1224
|
+
const listChristmasPayoutsCmd = async (options) => {
|
|
1225
|
+
const spinner = (0, ora_1.default)('Loading Christmas payouts...').start();
|
|
1226
|
+
const compact = isCompact();
|
|
1227
|
+
try {
|
|
1228
|
+
const data = await api_1.api.getTarPayPayouts({
|
|
1229
|
+
plan: 'christmas',
|
|
1230
|
+
status: options.status || 'pending_review',
|
|
1231
|
+
limit: compact ? 10 : 20,
|
|
1232
|
+
offset: ((options.page || 1) - 1) * (compact ? 10 : 20),
|
|
1233
|
+
});
|
|
1234
|
+
const payouts = data.results || [];
|
|
1235
|
+
spinner.stop();
|
|
1236
|
+
if (payouts.length === 0) {
|
|
1237
|
+
console.log(chalk_1.default.dim('\n No Christmas payouts found\n'));
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
// Info banner about $50 threshold
|
|
1241
|
+
console.log('');
|
|
1242
|
+
console.log(chalk_1.default.red('🎄 CHRISTMAS PAYOUTS') + chalk_1.default.dim(' (TarPay)'));
|
|
1243
|
+
console.log(chalk_1.default.dim(' Payouts > $50 require manual approval. < $50 are auto-sent.'));
|
|
1244
|
+
console.log('');
|
|
1245
|
+
if (compact) {
|
|
1246
|
+
payouts.forEach((p) => {
|
|
1247
|
+
const isPartial = p.has_partial_payments && (p.paid_percentage || 0) > 0;
|
|
1248
|
+
const statusIcon = p.status === 'completed' ? chalk_1.default.green('✓') :
|
|
1249
|
+
p.status === 'failed' ? chalk_1.default.red('✗') :
|
|
1250
|
+
isPartial ? chalk_1.default.cyan('%') : chalk_1.default.yellow('●');
|
|
1251
|
+
const email = p.user_email.length > 12 ? p.user_email.substring(0, 10) + '..' : p.user_email;
|
|
1252
|
+
const displayAmt = isPartial ? (p.remaining_amount || parseFloat(p.amount)) : parseFloat(p.amount);
|
|
1253
|
+
const amountStr = isPartial ? `${displayAmt.toFixed(2)}(${Math.round(p.paid_percentage || 0)}%)` : displayAmt.toFixed(2);
|
|
1254
|
+
console.log(` ${statusIcon} ${chalk_1.default.dim('#' + p.id)} ${chalk_1.default.red('xmas')} ${email} ${chalk_1.default.green(amountStr)} ${p.currency}`);
|
|
1255
|
+
});
|
|
1256
|
+
console.log(chalk_1.default.dim(`\n ${data.count} total\n`));
|
|
1257
|
+
}
|
|
1258
|
+
else {
|
|
1259
|
+
const table = new cli_table3_1.default({
|
|
1260
|
+
head: [
|
|
1261
|
+
chalk_1.default.cyan('ID'),
|
|
1262
|
+
chalk_1.default.cyan('User'),
|
|
1263
|
+
chalk_1.default.cyan('Remaining'),
|
|
1264
|
+
chalk_1.default.cyan('Crypto'),
|
|
1265
|
+
chalk_1.default.cyan('Progress'),
|
|
1266
|
+
chalk_1.default.cyan('Status'),
|
|
1267
|
+
],
|
|
1268
|
+
style: { head: [], border: [] },
|
|
1269
|
+
colWidths: [8, 24, 14, 10, 12, 14],
|
|
1270
|
+
});
|
|
1271
|
+
payouts.forEach((p) => {
|
|
1272
|
+
const isPartial = p.has_partial_payments && (p.paid_percentage || 0) > 0;
|
|
1273
|
+
const paidPct = p.paid_percentage || 0;
|
|
1274
|
+
const displayAmount = isPartial ? (p.remaining_amount || parseFloat(p.amount)) : parseFloat(p.amount);
|
|
1275
|
+
let statusIcon;
|
|
1276
|
+
if (p.status === 'completed') {
|
|
1277
|
+
statusIcon = chalk_1.default.green('✓ Done');
|
|
1278
|
+
}
|
|
1279
|
+
else if (p.status === 'failed') {
|
|
1280
|
+
statusIcon = chalk_1.default.red('✗ Failed');
|
|
1281
|
+
}
|
|
1282
|
+
else if (isPartial) {
|
|
1283
|
+
statusIcon = chalk_1.default.cyan(`% ${Math.round(paidPct)}%`);
|
|
1284
|
+
}
|
|
1285
|
+
else if (p.status === 'pending_review') {
|
|
1286
|
+
statusIcon = chalk_1.default.yellow('● Review');
|
|
1287
|
+
}
|
|
1288
|
+
else {
|
|
1289
|
+
statusIcon = chalk_1.default.blue('~ ' + p.status);
|
|
1290
|
+
}
|
|
1291
|
+
// Progress bar for partial payments
|
|
1292
|
+
let progressStr = '-';
|
|
1293
|
+
if (isPartial) {
|
|
1294
|
+
const filled = Math.round(paidPct / 10);
|
|
1295
|
+
const empty = 10 - filled;
|
|
1296
|
+
progressStr = chalk_1.default.green('█'.repeat(filled)) + chalk_1.default.dim('░'.repeat(empty));
|
|
1297
|
+
}
|
|
1298
|
+
table.push([
|
|
1299
|
+
chalk_1.default.dim(String(p.id)),
|
|
1300
|
+
p.user_email.length > 22 ? p.user_email.substring(0, 20) + '..' : p.user_email,
|
|
1301
|
+
chalk_1.default.green('$' + displayAmount.toFixed(2)),
|
|
1302
|
+
p.currency,
|
|
1303
|
+
progressStr,
|
|
1304
|
+
statusIcon,
|
|
1305
|
+
]);
|
|
1306
|
+
});
|
|
1307
|
+
console.log(table.toString());
|
|
1308
|
+
console.log(chalk_1.default.dim(`\n ${data.count} total\n`));
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
catch (error) {
|
|
1312
|
+
spinner.fail(chalk_1.default.red('Failed to load Christmas payouts'));
|
|
1313
|
+
console.log(chalk_1.default.dim(` ${error.response?.data?.detail || error.message}\n`));
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
const selectChristmasPayoutsInteractive = async (status) => {
|
|
1317
|
+
const spinner = (0, ora_1.default)('Loading Christmas payouts...').start();
|
|
1318
|
+
try {
|
|
1319
|
+
const data = await api_1.api.getTarPayPayouts({
|
|
1320
|
+
plan: 'christmas',
|
|
1321
|
+
status: status || 'pending_review',
|
|
1322
|
+
limit: 100,
|
|
1323
|
+
});
|
|
1324
|
+
const payouts = data.results || [];
|
|
1325
|
+
spinner.stop();
|
|
1326
|
+
if (payouts.length === 0) {
|
|
1327
|
+
console.log(chalk_1.default.dim('\n No Christmas payouts found\n'));
|
|
1328
|
+
return [];
|
|
1329
|
+
}
|
|
1330
|
+
const choices = payouts.map((p) => {
|
|
1331
|
+
const isPartial = p.has_partial_payments && (p.paid_percentage || 0) > 0;
|
|
1332
|
+
const displayAmount = isPartial ? (p.remaining_amount || parseFloat(p.amount)) : parseFloat(p.amount);
|
|
1333
|
+
const progressStr = isPartial ? chalk_1.default.cyan(` (${Math.round(p.paid_percentage || 0)}% paid)`) : '';
|
|
1334
|
+
return {
|
|
1335
|
+
name: `${chalk_1.default.red('🎄')} ${chalk_1.default.dim('#' + p.id)} ${p.user_email.substring(0, 25).padEnd(25)} ${chalk_1.default.green('$' + displayAmount.toFixed(2).padStart(10))} ${chalk_1.default.dim(p.currency)}${progressStr}`,
|
|
1336
|
+
value: p.id,
|
|
1337
|
+
short: `#${p.id}`,
|
|
1338
|
+
};
|
|
1339
|
+
});
|
|
1340
|
+
const { selected } = await inquirer_1.default.prompt([
|
|
1341
|
+
{
|
|
1342
|
+
type: 'checkbox',
|
|
1343
|
+
name: 'selected',
|
|
1344
|
+
message: 'Select Christmas payouts to process:',
|
|
1345
|
+
choices,
|
|
1346
|
+
pageSize: 15,
|
|
1347
|
+
loop: false,
|
|
1348
|
+
},
|
|
1349
|
+
]);
|
|
1350
|
+
return selected;
|
|
1351
|
+
}
|
|
1352
|
+
catch (error) {
|
|
1353
|
+
spinner.fail(chalk_1.default.red('Failed to load Christmas payouts'));
|
|
1354
|
+
return [];
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
const processChristmasPayoutsWithProgress = async (ids, action, percentage) => {
|
|
1358
|
+
const actionLabel = action === 'partial' ? `PARTIAL ${percentage}%` : action.toUpperCase();
|
|
1359
|
+
console.log('\n' + chalk_1.default.red('╔══════════════════════════════════════════════════════════════╗'));
|
|
1360
|
+
console.log(chalk_1.default.red('║') + chalk_1.default.bold.white(` 🎄 CHRISTMAS ${actionLabel} - ${ids.length} PAYOUT(S)... `.substring(0, 60)) + chalk_1.default.red('║'));
|
|
1361
|
+
console.log(chalk_1.default.red('╠══════════════════════════════════════════════════════════════╣'));
|
|
1362
|
+
const startTime = Date.now();
|
|
1363
|
+
// Show progress
|
|
1364
|
+
let processed = 0;
|
|
1365
|
+
const progressBar = (current, total) => {
|
|
1366
|
+
const percent = Math.round((current / total) * 100);
|
|
1367
|
+
const filled = Math.round(percent / 2);
|
|
1368
|
+
const empty = 50 - filled;
|
|
1369
|
+
return chalk_1.default.green('█'.repeat(filled)) + chalk_1.default.dim('░'.repeat(empty)) + ` ${percent}%`;
|
|
1370
|
+
};
|
|
1371
|
+
const progressInterval = setInterval(() => {
|
|
1372
|
+
processed = Math.min(processed + Math.random() * 10, 90);
|
|
1373
|
+
process.stdout.write(`\r${chalk_1.default.red('║')} ${progressBar(processed, 100)} ${chalk_1.default.red('║')}`);
|
|
1374
|
+
}, 200);
|
|
1375
|
+
try {
|
|
1376
|
+
let result;
|
|
1377
|
+
let successCount = 0;
|
|
1378
|
+
let failedCount = 0;
|
|
1379
|
+
const errors = [];
|
|
1380
|
+
if (action === 'partial') {
|
|
1381
|
+
result = await api_1.api.batchTarPayPartialPayouts(ids, percentage);
|
|
1382
|
+
successCount = result.success_count || 0;
|
|
1383
|
+
failedCount = result.failed_count || 0;
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
// Process approve/reject one by one
|
|
1387
|
+
for (const id of ids) {
|
|
1388
|
+
try {
|
|
1389
|
+
if (action === 'approve') {
|
|
1390
|
+
await api_1.api.approveTarPayPayout(id);
|
|
1391
|
+
}
|
|
1392
|
+
else {
|
|
1393
|
+
await api_1.api.rejectTarPayPayout(id);
|
|
1394
|
+
}
|
|
1395
|
+
successCount++;
|
|
1396
|
+
}
|
|
1397
|
+
catch (e) {
|
|
1398
|
+
failedCount++;
|
|
1399
|
+
errors.push(`#${id}: ${e.response?.data?.detail || e.message}`);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
result = { success: true, success_count: successCount, failed_count: failedCount, errors };
|
|
1403
|
+
}
|
|
1404
|
+
clearInterval(progressInterval);
|
|
1405
|
+
processed = 100;
|
|
1406
|
+
process.stdout.write(`\r${chalk_1.default.red('║')} ${progressBar(100, 100)} ${chalk_1.default.red('║')}\n`);
|
|
1407
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
1408
|
+
console.log(chalk_1.default.red('╠══════════════════════════════════════════════════════════════╣'));
|
|
1409
|
+
let icon, verb;
|
|
1410
|
+
if (action === 'approve') {
|
|
1411
|
+
icon = '✓';
|
|
1412
|
+
verb = 'APPROVED';
|
|
1413
|
+
}
|
|
1414
|
+
else if (action === 'partial') {
|
|
1415
|
+
icon = '%';
|
|
1416
|
+
verb = `PARTIAL ${percentage}% SENT`;
|
|
1417
|
+
}
|
|
1418
|
+
else {
|
|
1419
|
+
icon = '↩';
|
|
1420
|
+
verb = 'REJECTED';
|
|
1421
|
+
}
|
|
1422
|
+
console.log(chalk_1.default.red('║') + chalk_1.default.green(` ${icon} ${verb} `.substring(0, 60)) + chalk_1.default.red('║'));
|
|
1423
|
+
console.log(chalk_1.default.red('║') + ` Successful: ${chalk_1.default.bold.green(String(successCount).padEnd(5))} Failed: ${chalk_1.default.bold.red(String(failedCount).padEnd(5))} Time: ${chalk_1.default.dim(elapsed + 's')}`.padEnd(62) + chalk_1.default.red('║'));
|
|
1424
|
+
console.log(chalk_1.default.red('╚══════════════════════════════════════════════════════════════╝\n'));
|
|
1425
|
+
// Show errors if any
|
|
1426
|
+
const errList = result.errors || errors;
|
|
1427
|
+
if (errList.length > 0) {
|
|
1428
|
+
console.log(chalk_1.default.red(' Errors:'));
|
|
1429
|
+
errList.slice(0, 5).forEach((err) => {
|
|
1430
|
+
const errMsg = typeof err === 'string' ? err : `Payout ${err.payout_id}: ${err.error}`;
|
|
1431
|
+
console.log(chalk_1.default.dim(` - ${errMsg}`));
|
|
1432
|
+
});
|
|
1433
|
+
if (errList.length > 5) {
|
|
1434
|
+
console.log(chalk_1.default.dim(` ... and ${errList.length - 5} more errors`));
|
|
1435
|
+
}
|
|
1436
|
+
console.log('');
|
|
1437
|
+
}
|
|
1438
|
+
return result;
|
|
1439
|
+
}
|
|
1440
|
+
catch (error) {
|
|
1441
|
+
clearInterval(progressInterval);
|
|
1442
|
+
console.log(chalk_1.default.red('║') + chalk_1.default.red(' ✗ ERROR: ' + (error.response?.data?.detail || error.message).substring(0, 50).padEnd(52)) + chalk_1.default.red('║'));
|
|
1443
|
+
console.log(chalk_1.default.red('╚══════════════════════════════════════════════════════════════╝\n'));
|
|
1444
|
+
return { success: false };
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
const runChristmasPayoutsShell = async () => {
|
|
1448
|
+
setTitle('Christmas Payouts');
|
|
1449
|
+
// Show initial list
|
|
1450
|
+
await listChristmasPayoutsCmd({ status: 'pending_review' });
|
|
1451
|
+
const runLoop = async () => {
|
|
1452
|
+
const { command } = await inquirer_1.default.prompt([
|
|
1453
|
+
{
|
|
1454
|
+
type: 'input',
|
|
1455
|
+
name: 'command',
|
|
1456
|
+
message: chalk_1.default.red('christmas') + chalk_1.default.cyan(' > '),
|
|
1457
|
+
prefix: '',
|
|
1458
|
+
},
|
|
1459
|
+
]);
|
|
1460
|
+
const parts = command.trim().split(/\s+/);
|
|
1461
|
+
const cmd = parts[0]?.toLowerCase();
|
|
1462
|
+
if (cmd === 'back' || cmd === 'exit' || cmd === 'q') {
|
|
1463
|
+
setTitle('Payouts');
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
if (cmd === '') {
|
|
1467
|
+
return runLoop();
|
|
1468
|
+
}
|
|
1469
|
+
try {
|
|
1470
|
+
switch (cmd) {
|
|
1471
|
+
case 'refresh':
|
|
1472
|
+
case 'r':
|
|
1473
|
+
case 'list':
|
|
1474
|
+
case 'ls':
|
|
1475
|
+
await listChristmasPayoutsCmd({ status: 'pending_review' });
|
|
1476
|
+
break;
|
|
1477
|
+
case 'all':
|
|
1478
|
+
await listChristmasPayoutsCmd({});
|
|
1479
|
+
break;
|
|
1480
|
+
case 'done':
|
|
1481
|
+
case 'completed':
|
|
1482
|
+
await listChristmasPayoutsCmd({ status: 'completed' });
|
|
1483
|
+
break;
|
|
1484
|
+
case 'failed':
|
|
1485
|
+
await listChristmasPayoutsCmd({ status: 'failed' });
|
|
1486
|
+
break;
|
|
1487
|
+
case 'select':
|
|
1488
|
+
case 's':
|
|
1489
|
+
const selectedIds = await selectChristmasPayoutsInteractive('pending_review');
|
|
1490
|
+
if (selectedIds.length > 0) {
|
|
1491
|
+
const { action } = await inquirer_1.default.prompt([
|
|
1492
|
+
{
|
|
1493
|
+
type: 'list',
|
|
1494
|
+
name: 'action',
|
|
1495
|
+
message: `What do you want to do with ${selectedIds.length} selected payout(s)?`,
|
|
1496
|
+
choices: [
|
|
1497
|
+
{ name: chalk_1.default.green('✓ Approve & Send 100%'), value: 'approve' },
|
|
1498
|
+
{ name: chalk_1.default.cyan('% Pay Partial % (custom amount)'), value: 'partial' },
|
|
1499
|
+
{ name: chalk_1.default.yellow('↩ Reject'), value: 'reject' },
|
|
1500
|
+
{ name: chalk_1.default.dim('✗ Cancel'), value: 'none' },
|
|
1501
|
+
],
|
|
1502
|
+
},
|
|
1503
|
+
]);
|
|
1504
|
+
if (action === 'approve') {
|
|
1505
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1506
|
+
{
|
|
1507
|
+
type: 'confirm',
|
|
1508
|
+
name: 'confirm',
|
|
1509
|
+
message: chalk_1.default.yellow(`⚠️ Confirm: Approve ${selectedIds.length} payout(s)?`),
|
|
1510
|
+
default: false,
|
|
1511
|
+
},
|
|
1512
|
+
]);
|
|
1513
|
+
if (confirm) {
|
|
1514
|
+
await processChristmasPayoutsWithProgress(selectedIds, 'approve');
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
else if (action === 'partial') {
|
|
1518
|
+
const percentage = await getPercentageWithCustom();
|
|
1519
|
+
if (percentage !== null) {
|
|
1520
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1521
|
+
{
|
|
1522
|
+
type: 'confirm',
|
|
1523
|
+
name: 'confirm',
|
|
1524
|
+
message: chalk_1.default.yellow(`⚠️ Confirm: Pay ${percentage}% of ${selectedIds.length} payout(s)?`),
|
|
1525
|
+
default: false,
|
|
1526
|
+
},
|
|
1527
|
+
]);
|
|
1528
|
+
if (confirm) {
|
|
1529
|
+
await processChristmasPayoutsWithProgress(selectedIds, 'partial', percentage);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
else if (action === 'reject') {
|
|
1534
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1535
|
+
{
|
|
1536
|
+
type: 'confirm',
|
|
1537
|
+
name: 'confirm',
|
|
1538
|
+
message: chalk_1.default.yellow(`⚠️ Confirm: Reject ${selectedIds.length} payout(s)?`),
|
|
1539
|
+
default: false,
|
|
1540
|
+
},
|
|
1541
|
+
]);
|
|
1542
|
+
if (confirm) {
|
|
1543
|
+
await processChristmasPayoutsWithProgress(selectedIds, 'reject');
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
break;
|
|
1548
|
+
case 'approve':
|
|
1549
|
+
case 'a':
|
|
1550
|
+
const approveIds = await selectChristmasPayoutsInteractive('pending_review');
|
|
1551
|
+
if (approveIds.length > 0) {
|
|
1552
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1553
|
+
{
|
|
1554
|
+
type: 'confirm',
|
|
1555
|
+
name: 'confirm',
|
|
1556
|
+
message: chalk_1.default.yellow(`⚠️ Approve ${approveIds.length} payout(s)?`),
|
|
1557
|
+
default: false,
|
|
1558
|
+
},
|
|
1559
|
+
]);
|
|
1560
|
+
if (confirm) {
|
|
1561
|
+
await processChristmasPayoutsWithProgress(approveIds, 'approve');
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
break;
|
|
1565
|
+
case 'partial':
|
|
1566
|
+
case 'p':
|
|
1567
|
+
const partialIds = await selectChristmasPayoutsInteractive('pending_review');
|
|
1568
|
+
if (partialIds.length > 0) {
|
|
1569
|
+
const percentage = await getPercentageWithCustom();
|
|
1570
|
+
if (percentage !== null) {
|
|
1571
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1572
|
+
{
|
|
1573
|
+
type: 'confirm',
|
|
1574
|
+
name: 'confirm',
|
|
1575
|
+
message: chalk_1.default.yellow(`⚠️ Pay ${percentage}% of ${partialIds.length} payout(s)?`),
|
|
1576
|
+
default: false,
|
|
1577
|
+
},
|
|
1578
|
+
]);
|
|
1579
|
+
if (confirm) {
|
|
1580
|
+
await processChristmasPayoutsWithProgress(partialIds, 'partial', percentage);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
break;
|
|
1585
|
+
case 'reject':
|
|
1586
|
+
const rejectIds = await selectChristmasPayoutsInteractive('pending_review');
|
|
1587
|
+
if (rejectIds.length > 0) {
|
|
1588
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1589
|
+
{
|
|
1590
|
+
type: 'confirm',
|
|
1591
|
+
name: 'confirm',
|
|
1592
|
+
message: chalk_1.default.yellow(`⚠️ Reject ${rejectIds.length} payout(s)?`),
|
|
1593
|
+
default: false,
|
|
1594
|
+
},
|
|
1595
|
+
]);
|
|
1596
|
+
if (confirm) {
|
|
1597
|
+
await processChristmasPayoutsWithProgress(rejectIds, 'reject');
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
break;
|
|
1601
|
+
case 'help':
|
|
1602
|
+
case '?':
|
|
1603
|
+
console.log(chalk_1.default.red('\n 🎄 Christmas Payout Commands:'));
|
|
1604
|
+
console.log(chalk_1.default.dim(' ────────────────────────────────'));
|
|
1605
|
+
console.log(' refresh, r Refresh pending payouts');
|
|
1606
|
+
console.log(' list, ls List pending_review payouts');
|
|
1607
|
+
console.log(' all List all payouts (any status)');
|
|
1608
|
+
console.log(' done List completed payouts');
|
|
1609
|
+
console.log(' failed List failed payouts');
|
|
1610
|
+
console.log(' select, s Interactive selection mode');
|
|
1611
|
+
console.log(' approve, a Select & approve payouts');
|
|
1612
|
+
console.log(chalk_1.default.cyan(' partial, p Select & pay partial %'));
|
|
1613
|
+
console.log(' reject Select & reject payouts');
|
|
1614
|
+
console.log(' back, q Return to main payouts');
|
|
1615
|
+
console.log(chalk_1.default.dim('\n Note: Payouts > $50 need approval, < $50 auto-sent'));
|
|
1616
|
+
console.log('');
|
|
1617
|
+
break;
|
|
1618
|
+
default:
|
|
1619
|
+
console.log(chalk_1.default.red(` Unknown command: ${cmd}`));
|
|
1620
|
+
console.log(chalk_1.default.dim(' Type "help" for available commands\n'));
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
catch (e) {
|
|
1624
|
+
console.log(chalk_1.default.red(` Error: ${e.message}\n`));
|
|
1625
|
+
}
|
|
1626
|
+
await runLoop();
|
|
1627
|
+
};
|
|
1628
|
+
await runLoop();
|
|
1629
|
+
};
|
|
1182
1630
|
const runPayoutsShell = async () => {
|
|
1183
1631
|
setTitle('Payouts');
|
|
1184
1632
|
await showPayoutDashboard();
|
|
@@ -1245,30 +1693,19 @@ const runPayoutsShell = async () => {
|
|
|
1245
1693
|
}
|
|
1246
1694
|
}
|
|
1247
1695
|
else if (action === 'partial') {
|
|
1248
|
-
const
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
}
|
|
1261
|
-
]);
|
|
1262
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
1263
|
-
{
|
|
1264
|
-
type: 'confirm',
|
|
1265
|
-
name: 'confirm',
|
|
1266
|
-
message: chalk_1.default.yellow(`⚠️ Confirm: Pay ${percentage}% of ${selectedIds.length} payout(s)?`),
|
|
1267
|
-
default: false,
|
|
1268
|
-
},
|
|
1269
|
-
]);
|
|
1270
|
-
if (confirm) {
|
|
1271
|
-
await processPayoutsWithProgress(selectedIds, 'partial', percentage);
|
|
1696
|
+
const percentage = await getPercentageWithCustom();
|
|
1697
|
+
if (percentage !== null) {
|
|
1698
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
1699
|
+
{
|
|
1700
|
+
type: 'confirm',
|
|
1701
|
+
name: 'confirm',
|
|
1702
|
+
message: chalk_1.default.yellow(`⚠️ Confirm: Pay ${percentage}% of ${selectedIds.length} payout(s)?`),
|
|
1703
|
+
default: false,
|
|
1704
|
+
},
|
|
1705
|
+
]);
|
|
1706
|
+
if (confirm) {
|
|
1707
|
+
await processPayoutsWithProgress(selectedIds, 'partial', percentage);
|
|
1708
|
+
}
|
|
1272
1709
|
}
|
|
1273
1710
|
}
|
|
1274
1711
|
else if (action === 'cancel') {
|
|
@@ -1340,30 +1777,19 @@ const runPayoutsShell = async () => {
|
|
|
1340
1777
|
const partialPlan = args.find((a) => !a.startsWith('-') && isNaN(Number(a)));
|
|
1341
1778
|
const partialSelected = await selectPayoutsInteractive(partialPlan);
|
|
1342
1779
|
if (partialSelected.length > 0) {
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
}
|
|
1356
|
-
]);
|
|
1357
|
-
const { confirmPartial } = await inquirer_1.default.prompt([
|
|
1358
|
-
{
|
|
1359
|
-
type: 'confirm',
|
|
1360
|
-
name: 'confirmPartial',
|
|
1361
|
-
message: chalk_1.default.yellow(`⚠️ Pay ${partialPercentage}% of ${partialSelected.length} payout(s)?`),
|
|
1362
|
-
default: false,
|
|
1363
|
-
},
|
|
1364
|
-
]);
|
|
1365
|
-
if (confirmPartial) {
|
|
1366
|
-
await processPayoutsWithProgress(partialSelected, 'partial', partialPercentage);
|
|
1780
|
+
const partialPercentage = await getPercentageWithCustom();
|
|
1781
|
+
if (partialPercentage !== null) {
|
|
1782
|
+
const { confirmPartial } = await inquirer_1.default.prompt([
|
|
1783
|
+
{
|
|
1784
|
+
type: 'confirm',
|
|
1785
|
+
name: 'confirmPartial',
|
|
1786
|
+
message: chalk_1.default.yellow(`⚠️ Pay ${partialPercentage}% of ${partialSelected.length} payout(s)?`),
|
|
1787
|
+
default: false,
|
|
1788
|
+
},
|
|
1789
|
+
]);
|
|
1790
|
+
if (confirmPartial) {
|
|
1791
|
+
await processPayoutsWithProgress(partialSelected, 'partial', partialPercentage);
|
|
1792
|
+
}
|
|
1367
1793
|
}
|
|
1368
1794
|
}
|
|
1369
1795
|
break;
|
|
@@ -1374,6 +1800,11 @@ const runPayoutsShell = async () => {
|
|
|
1374
1800
|
case 'validator_v2':
|
|
1375
1801
|
await listPayoutsCmd({ plan: cmd });
|
|
1376
1802
|
break;
|
|
1803
|
+
case 'christmas':
|
|
1804
|
+
case 'xmas':
|
|
1805
|
+
// Christmas payouts subshell
|
|
1806
|
+
await runChristmasPayoutsShell();
|
|
1807
|
+
break;
|
|
1377
1808
|
case 'process':
|
|
1378
1809
|
// Process specific plan with interactive selection
|
|
1379
1810
|
const { processPlan } = await inquirer_1.default.prompt([
|
|
@@ -1452,6 +1883,7 @@ const runPayoutsShell = async () => {
|
|
|
1452
1883
|
console.log(' cancel [ids] Cancel payouts (interactive if no IDs)');
|
|
1453
1884
|
console.log(' process Process payouts by plan (interactive)');
|
|
1454
1885
|
console.log(' hermes/alpha/etc List payouts for specific plan');
|
|
1886
|
+
console.log(chalk_1.default.red(' christmas, xmas 🎄 Christmas payouts (TarPay)'));
|
|
1455
1887
|
console.log(' back, q Return to main menu');
|
|
1456
1888
|
console.log('');
|
|
1457
1889
|
break;
|